Ejemplo n.º 1
0
        /// <summary>
        /// 打包下载
        /// </summary>
        /// <param name="packFolderPath">需要打包的文件夹所在路径</param>
        /// <param name="fileNames">需要打包的文件集合(文件名)</param>
        /// <param name="zipFileName">打包后显示的文件名</param>
        public static void FilePackDownload(string packFolderPath, List <string> fileNames, string zipFileName)
        {
            using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(System.Text.Encoding.Default))//解决中文乱码问题
            {
                HttpContext httpContext = HttpContext.Current;
                httpContext.Response.Clear();
                httpContext.Response.ContentType = "application/zip";

                //兼容火狐和IE11的浏览器下载
                string packFileName = "";
                if (httpContext.Request.Headers["USER-AGENT"].IndexOf("MSIE") < 0 &&
                    httpContext.Request.Headers["USER-AGENT"].IndexOf("like Gecko") < 0)
                {
                    packFileName = "=?UTF-8?B?" + ALEncrypt.Base64EnCode(zipFileName) + "?=";
                }
                else
                {
                    packFileName = HttpUtility.UrlEncode(zipFileName, Encoding.UTF8);
                }

                httpContext.Response.AddHeader("content-disposition", "filename=" + packFileName);
                zip.AddDirectory(packFolderPath);
                foreach (string item in fileNames)
                {
                    try
                    {
                        zip.AddFile(item);
                    }
                    catch (Exception err)
                    {
                        ALMessage.RegMsg("打包下载失败,具体原因:" + err.Message);
                    }
                }

                zip.Save(httpContext.Response.OutputStream);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 文件下载
        /// </summary>
        /// <param name="filePath">所需下载文件的绝对路径</param>
        /// <param name="speed">限制速度以Byte为单位,若限制为200KB的下载速度则为1024 * 200</param>
        public static void FileDownload(string filePath, long speed, string downloadFileName, string mime)
        {
            HttpContext httpContext = HttpContext.Current;

            try
            {
                //验证:HttpMethod,为防止回传下载页面变成空白.只允许get下载
                switch (httpContext.Request.HttpMethod.ToUpper())
                {
                //目前只支持GET和HEAD方法
                case "GET":
                case "HEAD":
                    break;

                default:
                    httpContext.Response.StatusCode = 501;
                    return;
                }
                //验证:请求的文件是否存在
                if (!System.IO.File.Exists(filePath))
                {
                    httpContext.Response.StatusCode = 404;
                    return;
                }
                //定义局部变量
                long   startBytes = 0;
                int    packSize   = 1024 * 10; //分块读取,每块10K bytes
                string fileName   = downloadFileName;
                if (string.IsNullOrEmpty(fileName))
                {
                    fileName = Path.GetFileName(filePath);
                }
                FileStream   myFile     = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                BinaryReader br         = new BinaryReader(myFile);
                long         fileLength = myFile.Length;

                int    sleep             = (int)Math.Ceiling(1000.0 * packSize / speed);          //毫秒数:读取下一数据块的时间间隔
                string lastUpdateTiemStr = System.IO.File.GetLastWriteTimeUtc(filePath).ToString("r");
                string eTag = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTiemStr; //便于恢复下载时提取请求头;

                //验证:文件是否太大(2G)
                if (myFile.Length > Int32.MaxValue)
                {
                    httpContext.Response.StatusCode = 413;//请求实体太大
                    return;
                }
                //对应响应头ETag:文件名+文件最后修改时间
                if (httpContext.Request.Headers["If-Range"] != null)
                {
                    //----------上次被请求的日期之后被修改过--------------
                    if (httpContext.Request.Headers["If-Range"].Replace("\"", "") != eTag)
                    {
                        //文件修改过
                        httpContext.Response.StatusCode = 412;//预处理失败
                        return;
                    }
                }

                try
                {
                    //添加重要响应头、解析请求头、相关验证
                    httpContext.Response.Clear();
                    httpContext.Response.Buffer = false;
                    httpContext.Response.AddHeader("Content-MD5", ALEncrypt.Md5(myFile.ToString())); //用于验证文件
                    httpContext.Response.AddHeader("Accept-Ranges", "bytes");                        //重要:续传必须
                    httpContext.Response.AppendHeader("ETag", "\"" + eTag + "\"");                   //重要:续传必须
                    httpContext.Response.AppendHeader("Last-Modified", lastUpdateTiemStr);           //把最后修改日期写入响应
                    if (string.IsNullOrEmpty(mime))
                    {
                        httpContext.Response.ContentType = "application/octet-stream";//MIME类型:匹配任意文件类型
                    }
                    else
                    {
                        httpContext.Response.ContentType = mime;
                    }

                    if (httpContext.Request.Headers["USER-AGENT"].IndexOf("MSIE") < 0 &&
                        httpContext.Request.Headers["USER-AGENT"].IndexOf("like Gecko") < 0)
                    {
                        fileName = "=?UTF-8?B?" + ALEncrypt.Base64EnCode(fileName) + "?=";
                    }
                    else
                    {
                        fileName = HttpUtility.UrlEncode(fileName, Encoding.UTF8).Replace("+", "%20");
                    }

                    httpContext.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
                    httpContext.Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());
                    httpContext.Response.AddHeader("Connection", "Keep-Alive");
                    httpContext.Response.ContentEncoding = Encoding.UTF8;
                    if (httpContext.Request.Headers["Range"] != null)
                    {
                        //------如果是续传请求,则获取续传的起始位置,即已经下载到客户端的字节数------
                        httpContext.Response.StatusCode = 206;                                                //重要:续传必须,表示局部范围响应。初始下载时默认为200
                        string[] range = httpContext.Request.Headers["Range"].Split(new char[] { '=', '-' }); //"bytes=1474560-"
                        startBytes = Convert.ToInt64(range[1]);                                               //已经下载的字节数,即本次下载的开始位置
                        if (startBytes < 0 || startBytes >= fileLength)
                        {
                            return;
                        }
                    }
                    //如果是续传请求,告诉客户端本次的开始字节数,总长度,以便客户端将续传数据追加到startBytes位置后
                    if (startBytes > 0)
                    {
                        httpContext.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength));
                    }
                    //向客户端发送数据块
                    br.BaseStream.Seek(startBytes, SeekOrigin.Begin);
                    //分块下载,剩余部分可分成的块数
                    int maxCount = (int)Math.Ceiling((fileLength - startBytes + 0.0) / packSize);

                    //客户端未中断连接,并且数据没有传输完.则一直传输
                    for (int i = 0; i < maxCount && httpContext.Response.IsClientConnected; i++)
                    {
                        httpContext.Response.BinaryWrite(br.ReadBytes(packSize));
                        httpContext.Response.Flush();
                        if (sleep > 1)
                        {
                            Thread.Sleep(sleep);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    br.Close();
                    myFile.Close();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }