ASP.NET 文件下载问题总结

文件下载一般如下代码:

//从数据库中取出要下载的文件信息
//RuixinOA.BusinessFacade.RX_OA_FileManager os = new RX_OA_FileManager();
//EntityData data = os.GetFileDetail(id);
//int rowID = 0;
//rowID = int.Parse(Request.QueryString["rid"]);

Cofco.OA.Entity.Workflow.Attachment model = new Cofco.OA.Entity.Workflow.Attachment();
Cofco.OA.BLL.Workflow.AttachmentBL bll = new Cofco.OA.BLL.Workflow.AttachmentBL(connStr);
DataTable dt = new DataTable();
model = bll.GetModel(rowID,guID);

context.Response.Buffer = true;
context.Response.Clear();
context.Response.AddHeader("content-type", "application/x-msdownload");
context.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(model.Title));
if (model.Content.Length > 0)
{
context.Response.BinaryWrite(model.Content);

}
else
{

}
context.Response.Flush();
context.Response.End();

当然了,必要的你还要有容错处理功能,如
try
{

}
catch (Exception e)
{
throw;
}


=======================================================================================

问题:解决长文件名

在Asp.Net中写了一个附件上传和下载的程序,附件上传到数据库中,然后将附件的GUID保存起来,我们可以根据GUID来找到数据库中的附件,一般附件下载的代码是:

private void Download(string ID)
{
file = logic.GetAttachmentByID(new Guid(ID));
Response.AddHeader("Content-Type", file.Type);
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + HttpUtility.UrlEncode(file.FileName) + "\"");
Response.BinaryWrite(file.Data.ToArray());
Response.End();
}

这里比较重要的就是Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + HttpUtility.UrlEncode(file.FileName) + "\"");这里需要对中文文件名进行编码,默认是使用的UTF8编码。但是编码后文件名就会变得很长,比如我现在有一个文件叫:

招标送检样机项目检查登记表(终端)-空.XLS

我们进行网络抓包,可以看到在下载文件的时候的HTTP响应是:

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 44032
Content-Type: application/vnd.ms-excel
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 12.0.0.6219
X-AspNet-Version: 2.0.50727
Content-Disposition: attachment; filename="%e6%8b%9b%e6%a0%87%e9%80%81%e6%a3%80%e6%a0%b7%e6%9c%ba%e9%a1%b9%e7%9b%ae%e6%a3%80%e6%9f%a5%e7%99%bb%e8%ae%b0%e8%a1%a8(%e7%bb%88%e7%ab%af)-%e7%a9%ba.XLS"
Date: Wed, 25 Mar 2009 08:00:26 GMT

可以得到编码后文件名变成了:

%e6%8b%9b%e6%a0%87%e9%80%81%e6%a3%80%e6%a0%b7%e6%9c%ba%e9%a1%b9%e7%9b%ae%e6%a3%80%e6%9f%a5%e7%99%bb%e8%ae%b0%e8%a1%a8(%e7%bb%88%e7%ab%af)-%e7%a9%ba.XLS

这都是在HTTP头里面的,由于浏览器或者其他原因,对于这么长的HTTP头,系统会对字符串进行截止,那么就会造成下载的时候文件名不全或者干脆就是乱码的情况。我试了一下,这个文件的下载在IE8里面是完全正常的,但是在IE6里面就会造成字符串截止,变成“%a0%87送检样机项目检查登记表(终端)-空.XLS”。不同的浏览器截止的还不同。

解决办法有2种,1种是限制用户上传的文件的文件名或者我们在下载的时候写代码对文件名进行截止,避免出现乱码的情况,但是这样造成的用户体验并不好。那就用第2种解决办法:不使用UTF8的UrlEncode编码,直接使用gb2312编码输出中文名。

具体代码就是:
protected void Page_Load(object sender, EventArgs e)
{
PostLogic logic = new PostLogic();
if (Request.QueryString["AID"] != null)
{
Response.Clear();
Encoding code = Encoding.GetEncoding("gb2312");
Response.ContentEncoding = code;
Response.HeaderEncoding = code;//这句很重要
Attachment file = logic.GetAttachmentByID(new Guid(Request.QueryString["AID"].ToString()));
Response.AddHeader("Content-Type", file.Type);
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");//这里不进行编码工作,直接输出中文字符串
Response.BinaryWrite(file.Data.ToArray());
Response.End();
}
}


这样输出的就是长中文名了。我们再来抓包看一下HTTP响应的头:

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 44032
Content-Type: application/vnd.ms-excel
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 12.0.0.6219
X-AspNet-Version: 2.0.50727
Content-Disposition: attachment; filename="招标送检样机项目检查登记表(终端)-空.XLS"
Date: Wed, 25 Mar 2009 09:04:34 GMT

问题就这样解决了。当然,如果用户上传的是一个本来就很长很长的文件名的文件,那也是没有办法的,而且数据库中设计的字段可能也没有那么长。那就要在上传的时候做好限制了。


=============================================================================================================

文件名的字包含空格的问题

如果指定的文件名里包含了空格,FireFox就会截取空格前的部分作为默认文件名.
解决方法很简单:用双引号把文件名括起来:
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
Response.ContentType = "application/octet-stream";


不过还是有一个问题没解决,在IE中,如果文件名包含两个英文名点(dot, 字符'.')的话,它会在第一个点前自动加个"[1]",于是你原来的文件名"aaa.bbb.whatever"就变成了"aaa[1].bbb.whatever". 哪位知道怎么解决这个问题,给大家分享一下?

---------------------------------------------

根据微软的说明,第二个问题根本就无法解决。
我说,大家一起劝用户们扔掉IE吧!

总结:下面这个是我目前使用没有问题的代码:可以支持的文件名有:长文件名,特殊字符,繁体,简体,英文,空格,多扩展名等,如果遇到其他问题,我会在后面继续添加

//从数据库中取出要下载的文件信息
Cofco.OA.Entity.Workflow.Attachment model = new Cofco.OA.Entity.Workflow.Attachment();
Cofco.OA.BLL.Workflow.AttachmentBL bll = new Cofco.OA.BLL.Workflow.AttachmentBL(connStr);
DataTable dt = new DataTable();
model = bll.GetModel(rowID,guID);

context.Response.Buffer = true;
context.Response.Clear();
context.Response.Charset = "utf-8";
context.Response.HeaderEncoding = System.Text.Encoding.GetEncoding("gb2312");
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
this.EnableViewState = false;
//context.Response.AddHeader("content-type", "application/x-msdownload");
context.Response.AddHeader("content-type", "application/octet-stream");
context.Response.AddHeader("Content-Disposition", "attachment;filename=\"" + model.Title +"\"");
if (model.Content.Length > 0)
{
context.Response.BinaryWrite(model.Content);

}
else
{

}
context.Response.Flush();
context.Response.End();

 

http://hi.baidu.com/sjbh/blog/item/4ab49d11fc189074ca80c438.html

你可能感兴趣的:(asp.net)