在Asp.Net中寫了一個附件上傳和下載的程序,附件上傳到數據庫中,然后將附件的GUID保存起來,我們可以根據GUID來找到數據庫中的附件,一般附件下載的代碼是:
<!--<br /> <br /> Code highlighting PRoduced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->privatevoidDownload(stringID){file=logic.GetAttachmentByID(newGuid(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 OKCache-Control: privateContent-Length: 44032Content-Type: application/vnd.ms-ExcelServer: Microsoft-IIS/6.0X-Powered-By: ASP.NETMicrosoftSharePointTeamServices: 12.0.0.6219X-AspNet-Version: 2.0.50727Content-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編碼輸出中文名。
具體代碼就是:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->protectedvoidPage_Load(objectsender,EventArgse){PostLogiclogic=newPostLogic();if(Request.QueryString["AID"]!=null){Response.Clear();Encodingcode=Encoding.GetEncoding("gb2312");Response.ContentEncoding=code;Response.HeaderEncoding=code;//這句很重要Attachmentfile=logic.GetAttachmentByID(newGuid(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 OKCache-Control: privateContent-Length: 44032Content-Type: application/vnd.ms-excelServer: Microsoft-IIS/6.0X-Powered-By: ASP.NETMicrosoftSharePointTeamServices: 12.0.0.6219X-AspNet-Version: 2.0.50727Content-Disposition: attachment; filename="招標送檢樣機項目檢查登記表(終端)-空.XLS"Date: Wed, 25 Mar 2009 09:04:34 GMT
問題就這樣解決了。當然,如果用戶上傳的是一個本來就很長很長的文件名的文件,那也是沒有辦法的,而且數據庫中設計的字段可能也沒有那么長。那就要在上傳的時候做好限制了。
新聞熱點
疑難解答