使用 C# HttpClient 以多部分形式数据发送具有非 ASCII 文件名的文件时出现问题

问题描述 投票:0回答:1

在尝试使用 C# 的 HttpClient 和多部分表单数据将具有非 ASCII 文件名(例如,包含俄语字符的文件名)的文件上传到服务器时,我遇到了一个特殊问题。奇怪的是,虽然服务器无法识别文件名,并且在使用非 ASCII 文件名时似乎没有接收文件本身,但当我发送具有英文字母文件名的相同文件时,它工作得很好。当我使用 PostmanJavascript 发送具有俄语文件名的相同文件时,它也有效。

这是我的代码的简化版本:

HttpClient client = new HttpClient();
var content = new MultipartFormDataContent();

string filePath = "C:/path/to/file/файл.pdf"; // Example non-ASCII filename
var stream = new StreamContent(System.IO.File.OpenRead(filePath));
stream.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(stream, "file", "файл.pdf");

var response = await client.PostAsync("https://example.com/upload", content);

我尝试使用

Uri.EscapeDataString()
HttpUtility.UrlEncode()
对文件名进行编码,但无济于事。问题依然存在。

这个问题是否与我对文件名的编码方式有关?或者我还应该考虑其他因素吗?

c# httpclient multipartform-data
1个回答
1
投票

尝试使用 HttpWebRequest 而不是 HttpClient 上传文件

示例代码:

 public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
    {

        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.ContentType = "multipart/form-data; boundary=" + boundary;
        request.Method = "POST";
        request.KeepAlive = true;
        request.Credentials = System.Net.CredentialCache.DefaultCredentials;

        Stream requestStream = request.GetRequestStream();

        string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
        foreach (string key in nvc.Keys)
        {
            requestStream.Write(boundarybytes, 0, boundarybytes.Length);
            string formitem = string.Format(formdataTemplate, key, nvc[key]);
            byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
            requestStream.Write(formitembytes, 0, formitembytes.Length);
        }
        requestStream.Write(boundarybytes, 0, boundarybytes.Length);

        string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
        string header = string.Format(headerTemplate, paramName, "aaa.pdf", contentType);
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
        requestStream.Write(headerbytes, 0, headerbytes.Length);

        FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[fileStream.Length];
        int bytesRead = 0;
        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            requestStream.Write(buffer, 0, bytesRead);
        }
        fileStream.Close();

        byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
        requestStream.Write(trailer, 0, trailer.Length);
        requestStream.Close();

        WebResponse wresp = null;
        try
        {
            wresp = request.GetResponse();
            Stream stream2 = wresp.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            string result = reader2.ReadToEnd();
        }

        catch (WebException ex)
        {
            using (var stream = ex?.Response?.GetResponseStream())
                if (stream != null)
                    using (var reader = new StreamReader(stream))
                    {
                        string result = reader.ReadToEnd();
                        Console.WriteLine(reader.ReadToEnd());
                    }

        }
        catch (Exception ex)
        {
            if (wresp != null)
            {
                wresp.Close();
                wresp = null;
            }

        }
        finally
        {
            request = null;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.