在尝试使用 C# 的 HttpClient 和多部分表单数据将具有非 ASCII 文件名(例如,包含俄语字符的文件名)的文件上传到服务器时,我遇到了一个特殊问题。奇怪的是,虽然服务器无法识别文件名,并且在使用非 ASCII 文件名时似乎没有接收文件本身,但当我发送具有英文字母文件名的相同文件时,它工作得很好。当我使用 Postman 和 Javascript 发送具有俄语文件名的相同文件时,它也有效。
这是我的代码的简化版本:
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()
对文件名进行编码,但无济于事。问题依然存在。
这个问题是否与我对文件名的编码方式有关?或者我还应该考虑其他因素吗?
尝试使用 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;
}
}