Content-Disposition的使用和注意事项

我们在开发web系统时有时会有以下需求:

  • 希望某类或者某已知MIME 类型的文件(比如:*.gif;*.txt;*.htm)能够在访问时弹出“文件下载”对话框
  • 希望以原始文件名(上传时的文件名,例如:山东省政府1024号文件.doc)提供下载,但服务器上保存的地址却是其他文件名(如:12519810948091234_asdf.doc)
  • 希望某文件直接在浏览器上显示而不是弹出文件下载对话框
近日在使用Content-disposition的使用出现UTF-8识别不了的情况,经过HttpUtility.UrlEncode(fileName,Encoding.UTF8)编码后的文件名称直接显示给用户了,如图:
Content-Disposition的使用和注意事项
名称为uft 8格式,但是ie6.0却识别不了,很是不解,以前曾经使用此种方法是可行的,只好利用Google了,经查找网络里大多为像Qihangnet写的这篇文章似的,我也贴出来供大家使用。
Qihangnet的这篇文章跟我的想法基本是相似的,在
HttpContext.Current.Response.AddHeader("Content-Disposition " , "attachment ; filename=\"" + UTF_FileName(filename) + ".doc \";" );
.doc的后缀名是关键,我在没有写.doc或.txt之类的后缀时,依旧跟上图一样,加上后缀后utf 8格式的字符串自动识别成汉字了 ,至于为什么我还不是很清楚,贴出来让大家也注意一下就是了。

//------------------------------------------start-------------------------------------------------------------------

作者:Qihangnet 
出处:http://www.qihangnet.com/PermaLink,guid,db65d50a-ba90-4229-a3a2-71b4f1b407b9.aspx

 

    要解决上述需求就可以使用Content-disposition 来解决。第一个需求的解决办法是

Response.AddHeader "content-disposition "
,"attachment ; filename=fname.ext"

 
将上述需求进行归我给出如下例子代码:
public
 static
 void
 ToDownload(string
 serverfilpath,string
 filename)
{
FileStream fileStream =
 new
 FileStream(serverfilpath, FileMode.Open);
long
 fileSize =
 fileStream.Length;
HttpContext.Current.Response.ContentType =
 "application/octet-stream"
;
HttpContext.Current.Response.AddHeader("Content-Disposition "
, "attachment ; filename=\""
 +
 UTF_FileName(filename) +
 ".doc \";"
);
////attachment --- 作为附件下载

////inline --- 在线打开

HttpContext.Current.Response.AddHeader("Content-Length"
, fileSize.ToString());
byte
[] fileBuffer =
 new
 byte
[fileSize];
fileStream.Read(fileBuffer, 0, (int
)fileSize);
HttpContext.Current.Response.BinaryWrite(fileBuffer);
fileStream.Close();
HttpContext.Current.Response.End();
}
public
 static
 void
 ToOpen(string
 serverfilpath, string
 filename)
{
FileStream fileStream =
 new
 FileStream(serverfilpath, FileMode.Open);
long
 fileSize =
 fileStream.Length;
HttpContext.Current.Response.ContentType =
 "application/octet-stream"
;
HttpContext.Current.Response.AddHeader("Content-Disposition "
, "inline; filename=\""
 +
 UTF_FileName(filename) +
 ".doc\";" );  

    HttpContext.Current.Response.AddHeader("Content-Length"
, fileSize.ToString());
byte
[] fileBuffer =
 new
 byte
[fileSize];
fileStream.Read(fileBuffer, 0, (int
)fileSize);
HttpContext.Current.Response.BinaryWrite(fileBuffer);
fileStream.Close();
HttpContext.Current.Response.End();
}
private
 static
 string
 UTF_FileName(string
 filename)
{
return
 HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8);
}

 

简单的对上述代码做一下解析,ToDownload方法为将一个服务器上的文件(serverfilpath为服务器上的物理地址),以某文件名(filename)在浏览器上弹出“文件下载”对话框,而ToOpen是将服务器上的某文件以某文件名在浏览器中显示/打开的。注意其中我使用了UTF_FileName方法,该方法很简单,主要为了解决包含非英文/数字名称的问题,比如说文件名为“衣明志.doc”,使用该方法客户端就不会出现乱码了。
//*---------------------------end----------------------------------

园子里liping13599168的下载函数也不错,顺便也贴一下:
出处:http://www.cnblogs.com/liping13599168/archive/2008/07/31/672025.html


<!---->using  System.Threading;    
    
///   <summary>
    
///  
    
///   </summary>
    
///   <param name="_Request"> 读取客户端在 Web 请求期间发送的 HTTP 值 </param>
    
///   <param name="_Response"> 封装来自 ASP.NET 操作的 HTTP 响应信息 </param>
    
///   <param name="_fileName"> 目的文件名称 </param>
    
///   <param name="_fullPath"> 源文件路径 </param>
    
///   <param name="_speed"></param>
    
///   <returns> 是否成功 </returns>
     public   static   bool  ResponseFile(HttpRequest _Request, HttpResponse _Response,  string  _fileName,  string  _fullPath,  long  _speed)
    {
        
try
        {
            FileStream myFile 
=   new  FileStream(_fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            BinaryReader br 
=   new  BinaryReader(myFile);
            
try
            {
                _Response.AddHeader(
" Accept-Ranges " " bytes " );
                _Response.Buffer 
=   false ;
                
long  fileLength  =  myFile.Length;
                
long  startBytes  =   0 ;

                
double  pack  =   10240 // 10K bytes
                
// int sleep = 200;    // 每秒5次   即5*10K bytes每秒
                 int  sleep  =  ( int )Math.Floor( 1000   *  pack  /  _speed)  +   1 ;
                
if  (_Request.Headers[ " Range " !=   null )
                {
                    _Response.StatusCode 
=   206 ;
                    
string [] range  =  _Request.Headers[ " Range " ].Split( new   char [] {  ' = ' ' - '  });
                    startBytes 
=  Convert.ToInt64(range[ 1 ]);
                }
                _Response.AddHeader(
" Content-Length " , (fileLength  -  startBytes).ToString());
                
if  (startBytes  !=   0 )
                {
                    
// Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength-1, fileLength));
                }
                _Response.AddHeader(
" Connection " " Keep-Alive " );
                _Response.ContentType 
=   " application/octet-stream " ;
                _Response.AppendHeader(
" Content-Disposition " " attachment; filename=\ ""  + HttpUtility.UrlEncode(_fileName, System.Text.Encoding.UTF8) +  " .txt\ " ; " );

                br.BaseStream.Seek(startBytes, SeekOrigin.Begin);
                
int  maxCount  =  ( int )Math.Floor((fileLength  -  startBytes)  /  pack)  +   1 ;

                
for  ( int  i  =   0 ; i  <  maxCount; i ++ )
                {
                    
if  (_Response.IsClientConnected)
                    {
                        _Response.BinaryWrite(br.ReadBytes(
int .Parse(pack.ToString())));
                        Thread.Sleep(sleep);
                    }
                    
else
                    {
                        i 
=  maxCount;
                    }
                }
            }
            
catch
            {
                
return   false ;
            }
            
finally
            {
                br.Close();

                myFile.Close();
            }
        }
        
catch
        {
            
return   false ;
        }
        
return   true ;
}

// 调用方法
Page.Response.Clear();
bool  success  =  ResponseFile(Page.Request, Page.Response,  " 目的文件名称 " @" 源文件路径 " 1024000 );
if  ( ! success)
     Response.Write(
" 下载文件出错! " );
Page.Response.End();

你可能感兴趣的:(Web,浏览器,ext,asp.net,asp)