2

On my web email server, users can download attachments off their email.

When they receive a file name that is not in English, the text gets broken in IE 8/9, but it comes out totally fine in Chrome/Firefox. Here is the code that currently handles the download:

<%
    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>

So then I changed how the filename was being passed in the content-disposition to the following, hoping in vain that it would encode the string in UTF-8 correctly before saving on the client's computer:

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

Now I've solved one problem but I am faced with two new problems -_-

The first problem is that filename no longer gets broken when I download the file in IE 8/9 but it adds a weird [1] or [2] at the end of the file extension. So if I had 파일 1.docx, IE would save the document as 파일 1.docx[1]

The second problem is that in chrome, the browser takes the UTF-8 encoded string literally so it gets saved as 파일%20%1.docx. Note that the non-english part of the file is displayed properly but the empty space shows up as Unicode Character Code 20.

How do I go about solving this issue?

TtT23
  • 6,876
  • 34
  • 103
  • 174

2 Answers2

2

Solution

The most browser-compatible approach seems to be to put the desired filename into the url, rather than the Content-Disposition response header.

For example:

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

When the user clicks on the link above, it will save the correct filename. The following is from IE 8:

IE 8 file download prompt

So the question becomes - how do you get asp to recognize a url with the above format? The answer is that you use a url re-writer.

  • For IIS 7 and above, there is the official re-write module from Microsoft.
  • For IIS 6, you can use the latest versions (2.x) of the Ionics Isapi Rewrite Filter. Microsoft recommends this for older IIS versions.
  • For IIS 5, you can also use the Ionics Isapi Rewrite Filter, however you might have to use the (1.x) versions. To download an older version, see the "other downloads" section on the right hand side of the link. The documentation doesn't seem consistent in saying which IIS version is supported by which version of the filter.

If you are using IIS 4 or older, I strongly suggest you upgrade.

I don't have a lot of experience using URL re-writers, but I was able to get the Microsoft one working easily enough. I used the wizard to add a user-friendly rule:

Add user-friendly rule dialog

The rule itself was easy enough:

IIS re-write rule settings

As you can see, I am creating a rule that rewrites

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

to

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

When the web page (default2.asp) is called, it can grab the filename from the url parameter f.

Unrelated to your question, but you may also want to do some authentication to make sure that only the proper users have access to the file links, and therefore to your files.

Sources

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

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

Community
  • 1
  • 1
chue x
  • 18,573
  • 7
  • 56
  • 70
1

As a solution on the script side, first of all need to handle requested browser is Internet Explorer or not (sounds familiar, isn't it?).
I tried to be explanatory in the comments. Please consider the following example also and test it in all major browsers.

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
Kul-Tigin
  • 16,728
  • 1
  • 35
  • 64