当我try 使用C#‘S 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);

我try 使用Uri.EscapeDataString()HttpUtility.UrlEncode()对文件名进行编码,但无济于事.这个问题仍然存在.

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

推荐答案

try 使用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;
        }
    }

Csharp相关问答推荐

使用变量子根名称在C#中重新初始化SON文件

AutoMapper -如何为两个不同的用例设置单个映射?

如何使用Unity和MRTK3将手网添加到Hololens 2应用程序中

如何使用C#中的图形API更新用户配置文件图像

如何在Reflection. Emit中使用具有运行时定义的类型参数的泛型类型

在C#中使用类中的对象值

在LINQ Where子句中使用新的DateTime

为什么SignalR在每个Blazor服务器应用程序启动时最多启动8个服务器?

Blazor服务器端的身份验证角色

使用Orleans进行的单元测试找不到接口的实现

在实体框架中处理通用实体&S变更跟踪器

如何将MongoDB序列化程序设置为内部对象属性

如果是,我怎么才能让这个加75,如果不是,我怎么才能减go 100?

如何在.NET AOT中为所有枚举启用JsonStringEnumConverter

在被Interactive Server切换后,Blazor SSR页面无法正确加载JS

有条件地定义预处理器指令常量

如何在mediatr命令中访问HttpContext而不安装弃用的nuget包

此异步方法在重写方法中缺少等待运算符警告

用于ASP.NET核心的最小扩展坞

我如何为我的Blazor应用程序构建一个动态教程标注?