开发者

.Net MVC 2, return File that contains non-ASCII characters in the filename

开发者 https://www.devze.com 2023-04-04 18:32 出处:网络
I am working on a data export task that needs to be able to export in any language. All the languages that use strictly ASCII characters work just fine, but when I go for data exports in oriental lang

I am working on a data export task that needs to be able to export in any language. All the languages that use strictly ASCII characters work just fine, but when I go for data exports in oriental languages, it throws the following exception: "An invalid character was found in the mail header" With a bit of research, I determined that this was due to the RFC 2183 spec which states that "Parameter values longer than 78 characters, or which contain non-ASCII characters, MUST be encoded as specified in [RFC 2184]"

I read both of these documents and they weren't much of a help. I understand that there is a need to send the data in UTF-8 encoding in order to locate the file. However, this makes the downloaded file name appear as encoded UTF-8. As of now, I am encoding the file names into UTF using the functions I will post below. (All of this is in C#, MVC2)

    private static string GetCleanedFileName(string s)
    {
        char[] chars = s.ToCharArray();
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < chars.Length; i++)
        {
            string encodedString = EncodeChar(chars[i]);
            sb.Append(encodedString);
        }
        return sb.ToString();
    }

    private static string EncodeChar(char chr)
    {
        UTF8Encoding encoding = ne开发者_Go百科w UTF8Encoding();
        StringBuilder sb = new StringBuilder();
        byte[] bytes = encoding.GetBytes(chr.ToString());

        for (int index = 0; index < bytes.Length; index++)
        {
            sb.AppendFormat("%{0}", Convert.ToString(bytes[index], 16));
        }
        return sb.ToString();
    }

And the file is returned in the following function:

    [ActionName("FileLoad")]
    public ActionResult FileLoad()
    {
        string fileName = Request["fileName"];

        //Code that contains the path and file type Removed as it doesn't really apply to the question

        FileStream fs = new FileStream(filePath, FileMode.Open);
        return File(fs, exportName, GetCleanedFileName(fileName));
    }

Strictly speaking, this works. However, the entire file name ends up UTF-Encoded when it reaches the user. I'm looking for a way to pass back that pre-existing file to the user, such that it can keep its non-ASCII characters.

Any help is appreciated.


This seems to not be UTF-8 encoding, but a variant of utf-8-based URI Encoding. We could fix it up with:

private static string GetCleanedFileName(string s)
{
  StringBuilder sb = new StringBuilder();
  foreach(byte b in Encoding.UTF8.GetBytes(s))
  {
    if(b < 128 && b != 0x25)// ascii and not %
      sb.Append((char)b);
    else
      sb.Append('%').Append(b.ToString("X2"));
  }
  return sb.ToString();
}

You'll need to catch any other characters it considers special as well as % here. If those special characters are the same as those special to URIs, you could just use Uri.EscapeDataString(s).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号