Response.WriteFile 无法下载大文件解决方法

以前用Response.WriteFile(filename),但当遇到大文件时无法完整下载。

该方法最大的问题,它不是直接将数据抛到客户端,而是在服务器端(IIS)上缓存。当下载文件比较大时,服务器压力会很大,iis虽然支持2G大小的文件下载,但当文件上了很多M时,由于服务器以及网络等因素的影响,异常概率相当大。所以当需要下载大文件时就不能使用上面的方法了。

微软推荐以下方法代替之:

  • 将数据分成较小的部分,然后将其移动到输出流以供下载,从而获取这些数据。
  • 为用户提供用于下载文件的链接。
  • 使用 Microsoft ASP 3.0 进行下载或者与 ASP 一起使用 Software Artisans FileUp。
  • 创建 ISAPI 扩展以下载文件。
  • 使用 FTP 下载文件。

参考文档:http://support.microsoft.com/default.aspx?scid=kb;zh-cn;812406

C#相关代码如下:

public class FileDown
    {
        public FileDown()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }
        /// <summary>
        /// 参数为虚拟路径
        /// </summary>
        /// <param name="FileName"></param>
        /// <returns></returns>
        public static string FileNameExtension(string FileName)
        {
            return Path.GetExtension(MapPathFile(FileName));
        }
        /// <summary>
        /// 获取物理地址
        /// </summary>
        /// <param name="FileName"></param>
        /// <returns></returns>
        public static string MapPathFile(string FileName)
        {
            return HttpContext.Current.Server.MapPath(FileName);
        }
        /// <summary>
        ///使用WriteFile下载文件,参数为文件虚拟路径
        /// </summary>
        /// <param name="FileName"></param>
        public static void DownLoadold(string FileName)
        {
            string destFileName = MapPathFile(FileName);
            // Labelmsg.Text = destFileName;
            if (File.Exists(destFileName))
            {
                FileInfo fi = new FileInfo(destFileName);
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.ClearHeaders();
                HttpContext.Current.Response.Buffer = false;
                //HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename=" +HttpUtility.UrlEncode(Path.GetFileName(destFileName),System.Text.Encoding.Default));
                HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(Path.GetFileName(destFileName), System.Text.Encoding.UTF8));
                HttpContext.Current.Response.AppendHeader("Content-Length", fi.Length.ToString());
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                HttpContext.Current.Response.WriteFile(destFileName);
                HttpContext.Current.Response.Flush();
                HttpContext.Current.Response.End();
            }
        }
        /// <summary>
        /// 使用OutputStream.Write分块下载文件,参数为文件虚拟路径
        /// </summary>
        /// <param name="FileName"></param>
        public static void DownLoad(string FileName)
        {
            string filePath = MapPathFile(FileName);
            //指定块大小
            long chunkSize = 204800;
            //建立一个200K的缓冲区
            byte[] buffer = new byte[chunkSize];
            //已读的字节数
            long dataToRead = 0;
            FileStream stream = null;
            try
            {
                //打开文件
                stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                dataToRead = stream.Length;
                //添加Http头
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachement;filename=" + HttpUtility.UrlEncode(Path.GetFileName(filePath)));
                HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());
                while (dataToRead > 0)
                {
                    if (HttpContext.Current.Response.IsClientConnected)
                    {
                        int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
                        HttpContext.Current.Response.Flush();
                        HttpContext.Current.Response.Clear();
                        dataToRead -= length;
                    }
                    else
                    {
                        //防止client失去连接
                        dataToRead = -1;
                    }
                }
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write("Error:" + ex.Message);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
                HttpContext.Current.Response.Close();
            }
        }

        /// <summary>
        /// 使用OutputStream.Write分块下载文件,参数为文件绝对路径
        /// </summary>
        /// <param name="FileName"></param>
        public static void DownLoadFile(string filePath)
        {
            //string filePath = MapPathFile(FileName);
            //指定块大小
            long chunkSize = 204800;
            //建立一个200K的缓冲区
            byte[] buffer = new byte[chunkSize];
            //已读的字节数
            long dataToRead = 0;
            FileStream stream = null;
            try
            {
                //打开文件
                stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                dataToRead = stream.Length;
                //添加Http头
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachement;filename=" + HttpUtility.UrlEncode(Path.GetFileName(filePath)));
                HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());
                while (dataToRead > 0)
                {
                    if (HttpContext.Current.Response.IsClientConnected)
                    {
                        int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
                        HttpContext.Current.Response.Flush();
                        //HttpContext.Current.Response.Clear();
                        buffer = new Byte[chunkSize];
                        dataToRead = dataToRead - length;
                    }
                    else
                    {
                        //防止client失去连接
                        dataToRead = -1;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
                //HttpContext.Current.Response.Write("Error:" + ex.Message);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
                HttpContext.Current.Response.Close();
            }
        }
    }
此条目发表在学习笔记分类目录,贴了, 标签。将固定链接加入收藏夹。

4 则回应给 Response.WriteFile 无法下载大文件解决方法

  1. 内涵社说:

    太厉害啦!值得我们学习

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据