`

asp.net下载文件几种方式

 
阅读更多

protected void Button1_Click(object sender, EventArgs e)

{
微软为Response对象提供了一个新的方法TransmitFile来解决使用Response.BinaryWrite
下载超过400mb的文件时导致Aspnet_wp.exe进程回收而无法成功下载的问题。
Response.ContentType = "application/x-zip-compressed";
Response.AddHeader("Content-Disposition", "attachment;filename=z.zip");
string filename = Server.MapPath("DownLoad/aaa.zip");
Response.TransmitFile(filename);
}

//WriteFile实现下载
protected void Button2_Click(object sender, EventArgs e)

{
using System.IO;

string fileName ="aaa.zip";//客户端保存的文件名
string filePath=Server.MapPath("DownLoad/aaa.zip");//路径

FileInfo fileInfo = new FileInfo(filePath);
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.AddHeader("Content-Transfer-Encoding", "binary");
Response.ContentType = "application/octet-stream";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
Response.WriteFile(fileInfo.FullName);
Response.Flush();
Response.End();
}

//WriteFile分块下载
protected void Button3_Click(object sender, EventArgs e)

{

string fileName = "aaa.zip";//客户端保存的文件名
string filePath = Server.MapPath("DownLoad/aaa.zip");//路径

System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);

if (fileInfo.Exists == true)
{
const long ChunkSize = 102400;//100K 每次读取文件,只读取100K,这样可以缓解服务器的压力
byte[] buffer = new byte[ChunkSize];

Response.Clear();
System.IO.FileStream iStream = System.IO.File.OpenRead(filePath);
long dataLengthToRead = iStream.Length;//获取下载的文件总大小
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName));
while (dataLengthToRead > 0 && Response.IsClientConnected)
{
int lengthRead = iStream.Read(buffer, 0, Convert.ToInt32(ChunkSize));//读取的大小
Response.OutputStream.Write(buffer, 0, lengthRead);
Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
Response.Close();
}
}

//流方式下载
protected void Button4_Click(object sender, EventArgs e)

{
string fileName = "aaa.zip";//客户端保存的文件名
string filePath = Server.MapPath("DownLoad/aaa.zip");//路径

//以字符流的形式下载文件
FileStream fs = new FileStream(filePath, FileMode.Open);
byte[] bytes = new byte[(int)fs.Length];
fs.Read(bytes, 0, bytes.Length);
fs.Close();
Response.ContentType = "application/octet-stream";
//通知浏览器下载文件而不是打开
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();

}


最简单的方式是通过Response.Redirect指

但是这样的下载有几个问题:

1、无法下载不存在的文件:例如,我们若是想把程序动态(临时)产生的文字,当作一个文件下载的时候(也就是该文件其实原先并不是真的存在,而是动态产生的),就无法下载。

2、无法下载存储于数据库中的文件:这是类似的问题,该文件并没有真的存在,只是被存放在数据库中的某个位置(某笔记录中的某个栏位)的时候,就无法下载。

3、无法下载不存在于Web文件夹中的文件:文件确实存在,但该文件夹并不是可以分享出来的Web文件夹,例如,该文件的位置在C:\winnt,您总不会想要把该文件夹当作Web文件夹吧?这时候,由于您无法使用Redirect指向该位置,所以无法下载。

4、下载文件后,原本的页面将会消失。

典型的状况是,我们要让用户下载一个.txt文件或是.csv格式的Excel文件,但是...

1、这个文件可能是通过ASP.NET程序动态产生的,而不是确实存在于Server端的文件;

2、或是它虽然存在于伺服器端的某个实体位置,但我们并不想暴露这个位置(如果这个位置公开,很可能没有权限的用户也可以在网址栏上输入URL直接取得!!!)

3、或是这个位置并不在网站虚拟路径所在的文件夹中。(例如C:\Windows\System32...)


文件路径是不是有中文 zh-tw 这是繁体的!

public partial class FileDownLoad : System.Web.UI.Page    
    {    
        //提供下载的文件,不编码的话文件名会乱码    
        private string fileName = HttpContext.Current.Server.UrlEncode("规范.rar");    
        private string filePath = HttpContext.Current.Server.MapPath("规范.rar");    
        //使用TransmifFile下载文件    
        protected void btnDL1_Click(object sender, EventArgs e)    
        {    
            FileInfo info = new FileInfo(filePath);    
            long fileSize = info.Length;    
            Response.Clear();    
            Response.ContentType = "application/x-zip-compressed";    
            Response.AddHeader("Content-Disposition", "attachment;filename="+ fileName);    
            //不指明Content-Length用Flush的话不会显示下载进度    
            Response.AddHeader("Content-Length", fileSize.ToString());    
            Response.TransmitFile(filePath, 0, fileSize);    
            Response.Flush();    
            Response.Close();    
        }    
   
        //使用WriteFile下载文件    
        protected void btnDL2_Click(object sender, EventArgs e)    
        {    
            FileInfo info = new FileInfo(filePath);    
            long fileSize = info.Length;    
            Response.Clear();    
            Response.ContentType = "application/octet-stream";    
            Response.AddHeader("Content-Disposition", "attachement;filename=" + fileName);    
            //指定文件大小    
            Response.AddHeader("Content-Length", fileSize.ToString());    
            Response.WriteFile(filePath, 0, fileSize);    
            Response.Flush();    
            Response.Close();    
        }    
   
        //使用OutputStream.Write分块下载文件    
        protected void btnDL3_Click(object sender, EventArgs e)    
        {    
            //指定块大小    
            long chunkSize = 102400;    
            //建立一个100K的缓冲区    
            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头    
                Response.ContentType = "application/octet-stream";    
                Response.AddHeader("Content-Disposition", "attachement;filename=" + fileName);    
                Response.AddHeader("Content-Length", dataToRead.ToString());    
   
                while (dataToRead > 0)     
                {    
                    if (Response.IsClientConnected)    
                    {    
                        int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));    
                        Response.OutputStream.Write(buffer, 0, length);    
                        Response.Flush();    
                        Response.Clear();    
                        dataToRead -= length;    
                    }    
                    else     
                    {    
                        //防止client失去连接    
                        dataToRead = -1;    
                    }    
                }    
            }    
            catch (Exception ex)    
            {    
                Response.Write("Error:" + ex.Message);    
            }    
            finally     
            {    
                if (stream != null)     
                {    
                    stream.Close();    
                }    
                Response.Close();    
            }    
        }    
   
        //使用BinaryWrite下载文件,大文件效率不行    
        protected void btnDL4_Click(object sender, EventArgs e)    
        {    
            FileStream stream = null;    
            try     
            {    
                //读文件,大文件一次读入会占用大量内存    
                stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);    
                byte[] bytes = new byte[stream.Length];    
                stream.Read(bytes, 0, bytes.Length);    
                stream.Close();    
   
                //添加Http头    
                Response.ContentType = "application/octet-stream";    
                Response.AddHeader("Content-Disposition", "attachement;filename=" + fileName);    
                Response.AddHeader("Content-Length", bytes.Length.ToString());    
                Response.BinaryWrite(bytes);    
                Response.Flush();    
            }    
            catch (Exception ex)    
            {    
                Response.Write("Error:" + ex.Message);    
            }    
            finally     
            {    
                if (stream != null)     
                {    
                    stream.Close();    
                }    
                Response.Close();    
            }    
        }   
        //使用BinaryWrite分块下载文件    
        protected void btnDL5_Click(object sender, EventArgs e)    
        {    
            //指定区块和缓冲区    
            long chunkSize = 102400;    
            byte[] buffer = new byte[chunkSize];    
            FileStream stream = null;    
            long dataToRead = 0;    
            try     
            {    
                stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);    
                dataToRead = stream.Length;    
                //添加Http头    
                Response.ContentType = "application/octet-stream";    
                Response.AddHeader("Content-Disposition", "attachement;filename=" + fileName);    
                Response.AddHeader("Content-Length", dataToRead.ToString());    
   
                while (dataToRead > 0)     
                {    
                    if (Response.IsClientConnected)    
                    {    
                        int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));    
                        Response.BinaryWrite(buffer);    
                        Response.Flush();    
                        Response.Clear();    
   
                        dataToRead -= length;    
                    }    
                    else     
                    {    
                        dataToRead = -1;    
                    }    
                }    
   
            }    
            catch(Exception ex)    
            {    
                Response.Write("Error:" + ex.Message);    
            }    
            finally   
            {    
                if (stream != null)     
                {    
                    stream.Close();    
                }    
                Response.Close();    
            }    
        }    
    }  


以上除了第四种不推荐以外,其他的都可以,但是个人感觉分块下载的要好一点。没有仔细测试,所以可能有问题。

注意:对于中文文件名要编码才能正确显示。对于长中文文件名(UTF8编码后大于153字节的中文)即使编码了,还是有问题的.
response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
下载的程序里有了这句,一般在IE6的下载提示框上将正确显示文件的名字,无论是简体中文,还是日文。不过当时确实没有仔细测试文件名很长的中文文件名。先如今经过仔细测试,发现文字只要超过17个字,就不能下载了。经过好一番google和反复测试,总算对这个问题有了系统的认识,分列如下:

    . 通过我原来的方式,也就是先用URLEncoder编码,当中文文字超过17个时,IE6 无法下载文件。这是IE的bug,参见微软的知识库文章 KB816868 。原因可能是因为ie在处理 Response Header 的时候,对header的长度限制在150字节左右。而一个汉字编码成UTF-8是9个字节,那么17个字便是153个字节,所以便会报错。微软提供了一个补丁,可以从 这里 下载。这个补丁需要先安装ie6 sp1。因为我平时勤打补丁,我的IE6版本号是 6.0.2800.1106.xpsp2_xxxxx。所以我可能已经安装过了补丁,从而可以下载,但仍然出现文件名被截断的现象。微软让我们等待IE下一个service pack的发布。我今天也上网看到了好消息,迫于firefox的压力,IE7可能在年中发布。另外,Firefox 不支持这样的方式,将把编码后的%xx%xx直接作为文件名显示。


    . 我尝试使用 javamail 的MimeUtility.encode()方法来编码文件名,也就是编码成 =?gb2312?B?xxxxxxxx?= 这样的形式,并从 RFC1522 中找到对应的标准支持。不过很遗憾,IE6并不支持这一个标准。我试了一下,Firefox是支持的。

    . 按网上很多人提供的解决方案:将文件名编码成ISO8859-1似乎是有效的解决方案,代码如下:
    
     response.setHeader( "Content-Disposition", "attachment;filename=" + new String( fileName.getBytes("gb2312"), "ISO8859-1" ) );
    
     在确保附件文件名都是简体中文字的情况下,那么这个办法确实是最有效的,不用让客户逐个的升级IE。如果台湾同胞用,把gb2312改成big5就行。但现在的系统通常都加入了国际化的支持,普遍使用UTF-8。如果文件名中又有简体中文字,又有繁体中文,还有日文。那么乱码便产生了。另外,在我的电脑上Firefox(v1.0-en)下载也是乱码。

     折中考虑,我结合了一、三的方式,代码片断如下:

        String fileName = URLEncoder.encode(atta.getFileName(), "UTF-8");
        /*
         * see http://support.microsoft.com/default.aspx?kbid=816868
         */
        if (fileName.length() > 150) {
            String guessCharset = xxxx /*根据request的locale 得出可能的编码,中文操作系统通常是gb2312*/
             fileName = new String(atta.getFileName().getBytes(guessCharset), "ISO8859-1"); 
        }
         response.setHeader("Content-Disposition", "attachment; filename=" + fileName);


分享到:
评论

相关推荐

    ASP.NET页面之间传递值的几种方式(txt文件)

    ASP.NET页面之间传递值的几种方式,ASP.NET页面之间传递值的几种方式,ASP.NET页面之间传递值的几种方式

    ASP.NET中文件上传下载方法集合

    ASP.NET中文件上传下载方法集合的几种方法

    ASP.Net MVC 文件下载的几种方法

     在后台下载中又可以细分为几种下载方式  首先,在前台,我们需要一个标签  <a>Click to get file  Home为controller,download为action。  如果需要传一些参数,可以:  <a>Click to get file  在...

    ASP.NET学习大全

    ASP.NET文件上传程序的源代码.txt Asp.Net中文本换行.txt ASPNET中实现在线用户检测(使用后台守护线程).txt C# 读取计算机CPU,HDD信息.txt DataGrid导出EXCEL的几个方法(WebControl).txt DataGrid的打印预览和...

    asp.net学习大全(超全面的资料整合)

    ASP.NET文件上传程序的源代码.txt Asp.Net中文本换行.txt ASPNET中实现在线用户检测(使用后台守护线程).txt C# 读取计算机CPU,HDD信息.txt DataGrid导出EXCEL的几个方法(WebControl).txt DataGrid的打印预览和...

    ASP.NET应用开发案例教程

    8.3.4 其他几种客户端的用户状态管理方法 8.3.5 本小节提示 8.4 ASP.NETHTFP运行情况 8.4.1 HTFP运行情况介绍 8.4.2 HTFP处理程序 8.5 小结 8.6 习题 第9章 ASP.NET与XML 9.1 XML简介 9.1.1...

    Asp.Net Mvc 大文件上传,带进度条,附源码下载.rar

    环境 Asp.Net Mvc3 Vs2010 使用的脚本 jquery-1.5.1.min.js 、jquery.flash.js、 jquery.jqUploader.js 配置Webconfig ...

    ASP.NET应用与开发案例教程

    8.3.4其他几种客户端的用户状态管理方法 8.3.5本小节提示 8.4ASP.NETHTFP运行情况 8.4.1HTYP运行‘晴况介绍 8.4.2HTFP处理程序 8.5小结 8.6习题 第9章ASP.NET与XML 9.1XML简介 9.1.1什么是标记语言 9.1.2HTML的弊病 ...

    asp.net知识库

    在ASP.NET中使用WINDOWS验证方式连接SQL SERVER数据库 改进ADO.Net数据库访问方式 ASP.NET 2.0 绑定高级技巧 简单实用的DataSet更新数据库的类+总结 [ADO.NET]由数据库触发器引发的问题 为ASP.NET封装的SQL数据库...

    ASP.NET文件上传下载方法集合

    文件的上传下载是我们在实际项目开发过程中经常需要用到的技术,这里给出几种常见的方法,本文主要内容包括:  1、如何解决文件上传大小的限制  2、以文件形式保存到服务器  3、转换成二进制字节流保存到...

    Asp.net把图片存入数据库和读取图片的方法

    网上关于ASP.NET上传图片到数据库的资料非常多,常用的如下:存储图片类型数据有以下几种方式:1.将图片转换为二进制数组(byte[]) 代码如下:byte[] fileData = this.FileUpload1.FileBytes; 2. 根据路径将文件转换...

    十天学会ASP.net--我认为ASP.NET比ASP难很多,希望大家做好准备

    这样ASP.NET就有四种组合:VB+ACCESS,VB+SQL,C#+ACCESS,C#+SQL,本教程会使用C#+ACCESS,兼顾四种来写,让大家对ASP.NET有一个全面的认识。虽然说学习ASP.NET不需要任何ASP基础,但是我觉得如果大家ASP不会,还是...

    Asp.net实现多语言Demo.rar

    我实现多语言是利用了ASP.NET2.0的资源文件,其实据我所知除了资源文件的方式,在数据库里面建多个表中进行一个区域文化映射,也是解决国际化的一种方式(关于这种方式感兴趣的朋友可以自己试试) 现在我把实现国际化...

    ASP.NET的网页代码模型及生命周期

    在创建时,去掉【将代码放在单独的文件中】复选框的选择即可创建单文件页模型的ASP.NET文件。创建后文件会自动创建相应的HTML代码以便页面的初始化,示例代码如下所示。 “C#” %> <!DOCTYPE html PUBLIC “-//W3C/...

    asp.net导出数据到Excel的几种方法 学习心得

    asp.net导出到Excel也是个老生常谈的问题,在此归纳一下。 第一种是比较常用的方法。是利用控件的RenderControl功能,得到该控件生成的HTML,然后以Excel文件的类型输出到客户端。这种方法生成的其实是个HTML文件,...

    ASP.NET加密教程(MD5和SHA1加密几种方法)

    ASP.NET加密教程(MD5和SHA1加密几种方法) 很简单的一个文本文件,不要分简单的说明

    asp.net乱码解决方法

    asp.net乱码解决方法 1、从IE地址栏中直接输入这个地址,访问没错;  2、做一个静态页,其中包括这个超链接,点击访问也没错;  3、就是把这个链接添加到这个功能块中,点击访问那边接收到的是乱码。  一...

    ASP.NET刷新页面的几种方法详解

    介绍了ASP.NET刷新页面的几种方法,有需要的朋友可以参考一下

Global site tag (gtag.js) - Google Analytics