C# Multipart/Form-Data:为啥 PDF 文件上传没有问题但 JPG 失败?

Posted

技术标签:

【中文标题】C# Multipart/Form-Data:为啥 PDF 文件上传没有问题但 JPG 失败?【英文标题】:C# Multipart/Form-Data: Why do PDF files upload without problems but JPG fail?C# Multipart/Form-Data:为什么 PDF 文件上传没有问题但 JPG 失败? 【发布时间】:2021-11-29 22:46:36 【问题描述】:

我有一个要向其发送文件的 RESTFUL API 端点。问题是当我发送 JPEG 文件时,出现问题,Endpoint 无法看到文件。

这是我所知道的:

如果我使用 Fiddler 将 jpeg 文件发送到同一端点,它可以正常工作。 如果我将 pdf 重命名为 rickroll.jpg,则此代码可以正常工作(除了 API 端点确实会失败的图像大小调整,因为它实际上不是 jpg)。

我认为这在某种程度上是编码的问题,但我不知道我应该做些什么不同的事情来让它上传 jpeg 文件类型。

        private static HttpWebResponse CreateFileUploadRequest(string token)
    
        //Build Upload File API Request [POST]

        string url = ConfigurationManager.AppSettings["ApiUrl"] + "api/file/fileupload";

        var boundary = "-------------------------acebdf13572468";
        var boundaryStartBytes = System.Text.Encoding.ASCII.GetBytes("--" + boundary);
        var boundaryEndBytes = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "--");
        var contentType = "multipart/form-data; boundary=" + boundary;

        //build the outer request
        var httpWebRequest = BuildOuterRequest(url, contentType, token);

        //add the payload
        var fullFilePath = Settings.Instance.FileStoreFolderPath + @"\rickroll.jpg";
        var file = File.ReadAllBytes(fullFilePath);

        var contentDisposition = System.Text.Encoding.ASCII.GetBytes("\r\nContent-Disposition: form-data; name=\"file\"; filename=\"rickroll.jpg\"\r\n");
        var content = System.Text.Encoding.ASCII.GetBytes("Content-Type: image/jpeg\r\n\r\n");

        var data = boundaryStartBytes
            .Concat(contentDisposition)
            .Concat(content)
            .Concat(file)
            .Concat(boundaryEndBytes).ToArray();

        httpWebRequest.ContentLength = data.Length;

        //Send the file
        using (var streamWriter = httpWebRequest.GetRequestStream())
        
            streamWriter.Write(data, 0, data.Length);
            streamWriter.Flush();
            streamWriter.Close();
        

        return (HttpWebResponse)httpWebRequest.GetResponse();
    

服务器会检查以下内容:

            var request = HttpContext.Current.Request;
            if (request.Files.Count <= 0 || request.Files[0] == null)
                throw new ValidationException(Gui.SayApi("You must send a valid File."));

request.Files.Count 在我调试服务器端时显示为 0。

使用 NLOG,这是服务器端的内容

2021-10-11 11:26:11.8197 INFO 6376954837180627849 - Incoming messages:
 ---------------------------acebdf13572468
Content-Disposition: form-data; name="file"; filename="rickroll.png"
Content-Type: image/jpeg

???? JFIF      ?? ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90
?? C 




?? C        

??  j" ??               
?? ?    !1AQa"q2???#B??R??$3br?    
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz???????????????????????????????????????????????????????????????????????????            
?? ?  w !1AQaq"2?B????  #3R?br?
$4?%?&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz??????????????????????????????????????????????????????????????????????????   ? ?S???FM??)??&?\u?3H.:?nM4????@\u?2h????3H.:?nM?.:?nh?q?Srh?.:?nM?.:?nM?.:?nM

[REDACTED ENCODED JPEG]

+?? e????>|%????z??P?W?>???7u*?|?U?O?????T)???a?x??_
??G?i?4m>???,J)v?CF??h(??
O?????C???T????.'??---------------------------acebdf13572468--

2021-10-11 11:26:11.9378 INFO 6376954837180627849 - Outgoing messages: 
  "Message": "You must send a valid File.",
  "Status": "ERROR"

【问题讨论】:

抱歉,这是一个基本问题,但您确定文件对象被填充了吗?您是否使用正确的路径等。 旁注:由于您使用的是 using 语句,因此您无需手动刷新或关闭您的流编写器 - 即使您不需要,close 也会自动刷新 服务器的响应是什么? @ErmiyaEskandary 如果我获取一个 pdf 文件,请将其放入该文件夹并将其重命名为 rickroll.jpg(即使它不是 jpg),服务器端会获取 request.Files.Count = 1它继续处理文件,所以我知道路径是正确的。我修改了原始问题以显示发生了什么以及服务器端 barfs 在哪里的日志。 【参考方案1】:

原来我的关闭边界在它前面缺少 CRLF,因此它看起来与编码的 jpeg 是分开的。

var boundaryEndBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--");

我不清楚为什么 PDF 没有这个就没有问题,但 jpeg 和其他文件类型不会上传。

【讨论】:

以上是关于C# Multipart/Form-Data:为啥 PDF 文件上传没有问题但 JPG 失败?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 multipart/form-data 时不能正确发送带有 Unicode 的 POST 名称?

为啥在使用 multipart/form-data 时不能正确发送带有 Unicode 的 POST 名称?

在 c# 中使用 RestClient 作为 multipart/form-data 上传文件

为啥上传文件要使用multipart/form-data

在 c# HttpClient 4.5 中发布 multipart/form-data

C# form表单提交enctype="multipart/form-data" 与 enctype="application/x-www-form-urlencoded