如何在HttpClient / MultipartFormDataContent中禁用base64编码的文件名

时间:2014-02-21 08:22:04

标签: c# base64 dotnet-httpclient

我正在使用HttpClientMultipartFormDataContent POST到Java Web应用程序。我正在使用StringContents方法使用StreamContent上传多个MultipartFormDataContent.Add(HttpContent content, String name, String fileName)和一个我添加为HttpClient.PostAsync(String, HttpContent)的文件。

这很好用,除非我提供包含德语变音符号的 fileName (我还没有测试过其他非ASCII字符)。在这种情况下, fileName 正在进行base64编码。名为 99 2 LD 353TempÄüöß-1.txt

的文件的结果

看起来像这样:

 __utf-8_B_VGVtcCDvv73vv73vv73vv71cOTkgMiBMRCAzNTMgVGVtcCDvv73vv73vv73vv70tMS50eHQ___

Java服务器在其UI中显示此编码文件名,这会使用户感到困惑。我无法进行任何服务器端更改。

如何禁用此行为?任何帮助都将受到高度赞赏。

提前致谢!

4 个答案:

答案 0 :(得分:8)

我刚刚发现了与StrezzOr相同的限制,因为我所使用的服务器并不尊重文件名*标准。

我将文件名转换为UTF-8表示的字节数组,并将字节重新设置为"简单"的字符。 string(非UTF-8)。

此代码创建内容流并将其添加到多部分内容:

        FileStream fs = File.OpenRead(_fullPath);
        StreamContent streamContent = new StreamContent(fs);
        streamContent.Headers.Add("Content-Type", "application/octet-stream");
        String headerValue = "form-data; name=\"Filedata\"; filename=\"" + _Filename + "\"";
        byte[] bytes = Encoding.UTF8.GetBytes(headerValue);
        headerValue="";
        foreach (byte b in bytes)
        {
            headerValue += (Char)b;
        }
        streamContent.Headers.Add("Content-Disposition", headerValue);
        multipart.Add(streamContent, "Filedata", _Filename);

这适用于西班牙语口音。

希望这有帮助。

答案 1 :(得分:1)

我终于放弃并使用HttpWebRequest而不是HttpClient解决了任务。我必须手动构建标题和内容,但这使我忽略了发送非ASCII文件名的标准。我最终将未编码的UTF-8文件名塞进filename标题中,这是服务器接受我的请求的唯一方式。

答案 2 :(得分:1)

我最近发现了这个问题,我在这里使用了一种解决方法:

在服务器端:

private static readonly Regex _regexEncodedFileName = new Regex(@"^=\?utf-8\?B\?([a-zA-Z0-9/+]+={0,2})\?=$");

private static string TryToGetOriginalFileName(string fileNameInput) {
    Match match = _regexEncodedFileName.Match(fileNameInput);
    if (match.Success && match.Groups.Count > 1) {
        string base64 = match.Groups[1].Value;
        try {
            byte[] data = Convert.FromBase64String(base64);
            return Encoding.UTF8.GetString(data);
        }
        catch (Exception) {
            //ignored
            return fileNameInput;
        }
    }
    return fileNameInput;
}

然后像这样使用这个函数:

string correctedFileName = TryToGetOriginalFileName(fileRequest.FileName);

有效。

答案 3 :(得分:0)

为了在Content-Disposition标头文件名属性中传递非ascii字符,必须使用filename*属性而不是常规filename。请参阅规范here

要使用HttpClient执行此操作,您可以执行以下操作,

   var streamcontent = new StreamContent(stream);
   streamcontent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
      FileNameStar = "99 2 LD 353 Temp Äüöß-1.txt" 
   };
   multipartContent.Add(streamcontent);

标题最终会看起来像这样,

  Content-Disposition: attachment; filename*=utf-8''99%202%20LD%20353%20Temp%20%C3%84%C3%BC%C3%B6%C3%9F-1.txt