2009-10-19 42 views
3

我正在从ASP.NET页面向浏览器发送文件。要正确发送文件名我增加了头:发送文件时ASP.NET文件名编码

Response.ContentType = "application/octet-stream"; 
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename); 

的问题是,当文件包含空格(如“ABC DEF”)浏览器接收文件名的唯一的“ABC”的一部分。我尝试过:Server.HtmlEncode但它没有帮助。

你有什么想法如何解决这个问题?

PK

+0

Server.UrlEncode – Arthur 2009-10-19 12:11:35

回答

9

把文件名中的报价: -

Response.ContentType = "application/octet-stream"; 
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); 
4

不要以UrlEncode。这不是正确的方式来转义HTTP结构头参数中使用的值。由于该浏览器的错误处理,它只能在IE中运行,即使那时也不可靠。

对于一个空间,您可以使用Anthony(+1)建议的带引号的字符串。但Content-Disposition的肮脏事实是,没有可靠的支持转义方案,可用于在文件名参数中放置任意字符,如;,"或Unicode字符。唯一能够可靠跨浏览器的方法是完全删除文件名参数,并将所需的文件名作为UTF-8 + URL编码路径部分放在URI中。

请参阅this answer的一些背景。

+0

通常在Windows环境中;无论如何不是一个有效的文件名字符。我倾向于使用这个文件名参数的任何东西通过一个“合法文件名”消毒剂来取出这些字符。 – AnthonyWJones 2009-10-19 13:54:51

1

带有特殊符号(例如:space;#@!$)的文件名或者某些浏览器无法支持的非Unicode字符,或者导致客户机中的文件名不正确。 这是一篇由中国人称为chanext的文章,他给出了一个完美的方法来解决这个问题: 这篇文章给出了一个示例代码(用c#编写),以展示如何在所有四种流行的浏览器中得到完美的解决方案IE; Opera; Firefox和Chrome) 文件名“Microsoft.Asp.Net.doc”和“文件;; @ @%#^ & y.doc”都可以使用本文提供的方式正确输出。

http://ciznx.com/post/aspnetstreamdownloaddisplaynonunicodespacechar.aspx

0

基于由@chanext引用的代码,我清理了,把它变成一个单一的扩展方法。希望这可以帮助某人。

Partial Class Uploader 
    Inherits Page 

    Private Sub UploadFile() 
    Dim sFileName As String 
    Dim oPdf As MigraDoc.Rendering.PdfDocumentRenderer 

    sFileName = "File Name With Spaces #22.pdf" 

    With Me.Request.Browser 
     If .Browser = "InternetExplorer" OrElse .Browser = "IE" Then 
     sFileName = sFileName.EncodeForIE 
     Else 
     sFileName = String.Format("""{0}""", sFileName) 
     End If 
    End With 

    oPdf = New MigraDoc.Rendering.PdfDocumentRenderer 
    oPdf.Document = FileFactory.CreatePdf() 
    oPdf.RenderDocument() 

    Using oStream As New MemoryStream 
     oPdf.Save(oStream, False) 

     Me.Response.Clear() 
     Me.Response.ContentType = "application/pdf" 
     Me.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", sFileName)) 
     Me.Response.AddHeader("content-length", oStream.Length) 
     Me.Response.BinaryWrite(oStream.ToArray) 
    End Using 

    Me.Response.Flush() 
    Me.Response.End() 
    End Sub 
End Class 



Public Module StringExtensions 
    <Extension()> 
    Public Function EncodeForIE(Url As String) As String 
    Dim _ 
     sReservedChars, 
     sEncodedString As String 

    sReservedChars = "$-_.+!*'(),@=&" 

    With New StringBuilder 
     Url.ToList.ForEach(Sub(C) 
          If Char.IsLetterOrDigit(C) OrElse sReservedChars.Contains(C) Then 
          .Append(C) 
          Else 
          With New StringBuilder 
           C.ToBytes.ToList.ForEach(Sub(B) 
                  .AppendFormat("%{0}", Convert.ToString(B, 16)) 
                 End Sub) 

           sEncodedString = .ToString 
          End With 

          .Append(sEncodedString) 
          End If 
         End Sub) 

     Return .ToString 
    End With 
    End Function 

    <Extension()> 
    Public Function ToBytes(Chr As Char) As Byte() 
    Return Encoding.UTF8.GetBytes(Chr.ToString) 
    End Function 
End Module