发布多部分表单数据问题

Posted

技术标签:

【中文标题】发布多部分表单数据问题【英文标题】:Posting Multipart Form Data Issue 【发布时间】:2019-11-19 14:55:10 【问题描述】:

我正在使用 HttpWebRequest 发布到 MMS API。帖子的正文包含有关交付的 XML 数据和作为 MIME 多部分附件的 MMS 消息,需要进行 Base64 编码。

发帖成功,但我只收到文字,没有图片。

在查看我的代码时,似乎可以构建表单数据,但是当我将其转换回字符串时,文件数据丢失了。

str 变量的内容:

------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="用户名"

三部曲 ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="密码"

ZBo8KE6m ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="号码"

61402720898 ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="主题"

测试邮件主题

------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="消息"

测试消息正文。

------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="type0"

图像/JPEG ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称="type1"

图像/JPEG ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称=“名称0”

凭证.png ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称=“名称1”

二维码.png ------------f2de17263b724d5a919b14a6834c489f 内容处置:表单数据;名称=“附件0”;文件名="凭证.png" 内容类型:image/jpeg

�PNG

    private static readonly Encoding encoding = Encoding.UTF8;
    public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
    
        string formDataBoundary = String.Format("----------0:N", Guid.NewGuid());
        string contentType = "multipart/form-data; boundary=" + formDataBoundary;

        byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);
        var str = Encoding.UTF8.GetString(formData);

        return PostForm(postUrl, userAgent, contentType, formData);
    

    private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
    
        Stream formDataStream = new System.IO.MemoryStream();
        byte[] formData = new byte[0];
        bool needsCLRF = false;
        try
        
            foreach (var param in postParameters)
            
                // add a CRLF to allow multiple parameters to be added (skip it on the 1st parameter)
                if (needsCLRF)
                    formDataStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));

                needsCLRF = true;

                if (param.Value is FileParameter)
                
                    FileParameter fileToUpload = (FileParameter)param.Value;

                    // add just the first part of this param, since we will write the file data directly to the stream
                    string header = string.Format("--0\r\nContent-Disposition: form-data; name=\"1\"; filename=\"2\"\r\nContent-Type: 3\r\n\r\n",
                        boundary,
                        param.Key,
                        fileToUpload.FileName ?? param.Key,
                        fileToUpload.ContentType ?? "application/octet-stream");

                    formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));

                    // write the file to the stream
                    string str = Convert.ToBase64String(fileToUpload.File);
                    byte[] myBytes = Convert.FromBase64String(str);
                    formDataStream.Write(myBytes, 0, myBytes.Length);
                                        
                else
                
                    string postData = string.Format("--0\r\nContent-Disposition: form-data; name=\"1\"\r\n\r\n2",
                        boundary,
                        param.Key,
                        param.Value);
                    formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
                
            

            // add the end of the request. Start with a newline
            string footer = "\r\n--" + boundary + "--\r\n";
            formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));

            // dump stream into byte array
            formDataStream.Position = 0;
            formData = new byte[formDataStream.Length];
            formDataStream.Read(formData, 0, formData.Length);
            formDataStream.Close();
        
        catch (Exception ex)
        
            gFunc.ProcessError(true, ex.ToString(), "Post Data");
        
        return formData;
    

【问题讨论】:

我设法通过更改 byte[] myBytes = Convert.FromBase64String(str); 解决了部分问题到 byte[] myBytes = encoding.GetBytes(str);但是当我收到彩信时,我仍然只收到文字,没有图片。 【参考方案1】:

原来问题出在帖子数据上。

删除“Content-Distribution”中文件参数的附加字段后,它起作用了。

以前: 内容处置:表单数据;名称=“附件0”;文件名="凭证.png" 内容类型:image/jpeg

现在: 内容处置:表单数据;名称="附件0"

【讨论】:

以上是关于发布多部分表单数据问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Jetty HttpClient 中进行多部分/表单数据发布

API Gateway - 发布多部分/表单数据

如何使用 fetch 发布多部分表单数据?

如何将多部分/表单数据从 android 发送到 Web 服务器?

如果“内容类型”:“多部分/表单数据”,CORS 问题

使用 Undertow 的多部分表单数据示例