ASP Classic使用UTF-8正确处理文件保存

时间:2013-01-21 06:25:54

标签: asp-classic utf-8

在我的网络电子邮件服务器上,用户可以通过电子邮件下载附件。

当他们收到的文件名不是英文时,文字会在IE 8/9中被破坏,但在Chrome / Firefox中它完全没问题。以下是当前处理下载的代码:

<%
    attachfile = request("file")%>
<%
    files = Split(attachfile,"\")
    Set fso = CreateObject("Scripting.FileSystemObject")

    Response.Clear
    'Response.CharSet="UTF-8" 
    Response.ContentType = "application/unknown"
    Response.AddHeader "Pragma", "no-cache"
    Response.AddHeader "Expires", "0"
    Response.AddHeader "Content-Transfer-Encoding", "binary"
    Response.AddHeader "Content-Disposition","attachment; filename = " & files(Ubound(files)) 

    Set objStream = Server.CreateObject("ADODB.Stream")
    objStream.Open

    objStream.Type = 1 
    objStream.LoadFromFile attachfile

    Response.BinaryWrite objStream.Read
    Response.Flush

    objStream.Close : Set objStream = nothing

    Set fso = Nothing
%>
</BODY>
</HTML>

然后我改变了文件名在内容处理中传递给以下内容的方式,希望在保存到客户端计算机上之前它会正确编码UTF-8中的字符串:

Response.AddHeader "Content-Disposition","attachment; filename = " & Server.URLEncode(files(Ubound(files))) 

现在我已经解决了一个问题,但我遇到了两个新问题-_-

第一个问题是当我在IE 8/9中下载文件时文件名不再被破坏,但它在文件扩展名的末尾添加了一个奇怪的[1]或[2]。因此,如果我有파일1.docx,IE会将文档保存为파일1.docx [1]

第二个问题是,在chrome中,浏览器逐字地采用UTF-8编码的字符串,因此它被保存为파일%20%1.docx。请注意,文件的非英语部分正确显示,但空白区域显示为Unicode字符代码20.

如何解决此问题?

2 个答案:

答案 0 :(得分:2)

<强>解决方案

最兼容浏览器的方法似乎是将所需的文件名放入网址,而不是Content-Disposition响应标头。

例如:

http://localhost/[webpage]/파일.docx

当用户点击上面的链接时,它将保存正确的文件名。以下是来自IE 8:

IE 8 file download prompt

所以问题变成了 - 你如何让asp识别上述格式的网址?答案是您使用网址重写器。

如果您使用的是IIS 4或更早版本,我强烈建议您升级。

我没有很多使用URL重写器的经验,但我能够轻松地使Microsoft工作。我使用向导添加了user-friendly规则:

Add user-friendly rule dialog

规则本身很容易:

IIS re-write rule settings

如您所见,我正在创建一个重写

的规则
http://localhost/default2/foo.doc/
http://localhost/default2/foo.doc (also works)

http://localhost/default2.asp?f=foo.doc

当调用网页(default2.asp)时,它可以从url参数f中获取文件名。

与您的问题无关,但您可能还需要进行一些身份验证,以确保只有正确的用户才能访问文件链接,从而访问您的文件。

<强>来源

How to encode the filename parameter of Content-Disposition header in HTTP?

How to encode UTF8 filename for HTTP headers? (Python, Django)

答案 1 :(得分:1)

作为脚本方面的解决方案,首先需要处理请求的浏览器是否是Internet Explorer(听起来很熟悉,不是吗?)。我试图在评论中解释。请同时考虑以下示例并在所有主流浏览器中对其进行测试。

Sub AddDisposHdr(ByVal FileName)
    If InStr(Request.ServerVariables("HTTP_USER_AGENT"), "MSIE") Then 'Internet Explorer
        Dim FileExt
        If InStr(FileName, ".") > 1 And Len(FileName) > 2 Then 'handling files without extension
            'file extension. shouldn't be encoded to get rid of meaningless square brackets in file names
            FileExt = Mid(FileName, InStrRev(FileName, "."))
            FileName = Mid(FileName, 1, InStrRev(FileName, ".") - 1) 'file name without extension
            FileName = Replace(Server.URLEncode(FileName), "+", " ") 'urlencode + replace plus signs with spaces
            FileName = FileName & FileExt
        End If
        Response.AddHeader "Content-Disposition", "attachment; filename=""" & FileName & """"
    Else ' Not Internet Explorer
        'According to RFC 2231 @ http://tools.ietf.org/html/rfc2231#section-3
        Response.AddHeader "Content-Disposition", "attachment; filename*=UTF-8''" &  _ 
        Server.URLPathEncode(FileName) ' It's an undocumented method.
        'Server.UrlPathEncode is used specifically to encode path names.
        'Its difference from UrlEncode is encodes space as "%20" not "+" 
        'and it doesn't encode the following characters at all : $#!&*.+-/@:? but UrlEncode does.
    End If
End Sub

Response.ContentType = "application/x-download"
AddDisposHdr FileNames("こんにちは 1.zip")
Response.Write "1" 'something to output