发送文件时的ASP.NET文件名编码

时间:2009-10-19 12:10:18

标签: asp.net encoding

我正在从ASP.NET页面向浏览器发送文件。要正确发送文件名,我正在添加标题:

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

问题是当文件包含空格(例如“abc def”)时,浏览器只接收文件名的“abc”部分。我试过:Server.HtmlEncode但它没有帮助。

你知道如何解决这个问题吗?

PK

4 个答案:

答案 0 :(得分:9)

将文件名放在引号中: -

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

答案 1 :(得分:4)

不要UrlEncode。这不是在HTTP结构化标头参数中转义值的正确方法。它只适用于IE,因为浏览器的错误处理,甚至不可靠。

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

有关背景信息,请参阅this answer

答案 2 :(得分:1)

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

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

答案 3 :(得分: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