简体   繁体   English

发布MultipartFormData时发出问题c#

[英]Issue while posting MultipartFormData c#

Sorry for this question, I know there are too many discussion already did on the same topic, I tried everything but I am not able to identify the exact issue. 对不起这个问题,我知道关于同一主题的讨论已经太多了,我尝试了一切,但我无法确定确切的问题。 So I need some input from experts. 所以我需要专家的一些意见。

Requirement: Its very simple, we to post two text fieds as string and one xml file. 要求:非常简单,我们将两个文本fieds发布为字符串和一个xml文件。

Below the sample network call trace when I am doing the same using browser. 在我使用浏览器执行相同操作时,示例网络调用跟踪下方。

浏览器调用

C# code to acheive the same. C#代码实现相同。

  using (HttpClient http = new HttpClient())
        {
            http.BaseAddress = new Uri("http://**.168.215.***");
            http.DefaultRequestHeaders.Add("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36");
            http.DefaultRequestHeaders.Add("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundarydsads");
            MultipartFormDataContent content = new MultipartFormDataContent();
            HttpContent datasource = new StringContent("test", Encoding.UTF8);
            HttpContent feedtype = new StringContent("metadata-and-url", Encoding.UTF8);
            string xmlText = File.ReadAllText(fi.FullName);
            HttpContent data = new ByteArrayContent(File.ReadAllBytes(fi.FullName));
            content.Add(datasource, "datasource");
            content.Add(feedtype, "feedtype");
            content.Add(data, "data", "text.xml");

            var response = http.PostAsync("/xmlfeed", content).Result;

        }

The response is "Bad Request 400". 响应是“错误请求400”。 Please provide comments on this. 请提供意见。

The MultipartFormDataContent doesn't know the boundary. MultipartFormDataContent不知道边界。 You only set the boundary in the headers. 您只在标题中设置边界。

Use a constructor, that includes a boundary, read more here: https://msdn.microsoft.com/en-us/library/hh138232(v=vs.118).aspx 使用包含边界的构造函数,在此处阅读更多内容: https//msdn.microsoft.com/en-us/library/hh138232(v = vs.118).aspx

I've been successfully using this helper class for creating HttpMultipartPostReuest for a long time. 我已成功使用这个助手类长时间创建HttpMultipartPostReuest

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace GeneralHelpers.Web
{

    public class HttpMultipartPostReuest
    {

        private const string FileParamContentDisposition = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";
        private const string GeneralParamContentDisposition = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
        private const string MultipartContent = "multipart/form-data; boundary=";

        private readonly string _boundary;
        private readonly byte[] _boundaryBytes;
        private readonly string _contentType;
        private readonly Encoding _encoding = Encoding.UTF8;
        private readonly HttpWebRequest _request;

        public string Boundary { get { return this._boundary; } }

        public string ContentType { get { return this._contentType; } }

        public HttpMultipartPostReuest(string url, Dictionary<string, object> postParameters)
        {
            this._boundary = HttpMultipartPostReuest.GenerateBoundary();
            this._boundaryBytes = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}\r\n", this._boundary));
            this._contentType = HttpMultipartPostReuest.MultipartContent + this._boundary;

            this._request = WebRequest.Create(url) as HttpWebRequest;
            if (this._request == null)
            {
                throw new NullReferenceException("request is not a http request");
            }

            byte[] formData = this.GetMultipartFormData(postParameters);

            // Set up the request properties.
            this._request.Method = WebRequestMethods.Http.Post;
            this._request.ContentType = this._contentType;
            this._request.ContentLength = formData.Length;
            this._request.Credentials = System.Net.CredentialCache.DefaultCredentials;

            // Send the form data to the request.
            using (Stream requestStream = this._request.GetRequestStream())
            {
                requestStream.Write(formData, 0, formData.Length);
                requestStream.Close();
            }
        }

        private static string GenerateBoundary()
        {
            return string.Format("---------------------------{0}", DateTime.Now.Ticks.ToString("x"));
        }

        public WebResponse GetResponce()
        {
            return this._request.GetResponse();
        }

        private byte[] GetMultipartFormData(Dictionary<string, object> postParameters)
        {
            using (Stream formDataStream = new MemoryStream())
            {
                foreach (var param in postParameters)
                {
                    //always wtiring boundary
                    formDataStream.Write(this._boundaryBytes, 0, this._boundaryBytes.Length);

                    FileParameter value = param.Value as FileParameter;
                    if (value != null)
                    {
                        FileParameter fileToUpload = value;

                        // Add just the first part of this param, since we will write the file data directly to the Stream
                        string header = string.Format(HttpMultipartPostReuest.FileParamContentDisposition, param.Key, fileToUpload.FileName ?? param.Key,
                            fileToUpload.ContentType);

                        formDataStream.Write(this._encoding.GetBytes(header), 0, this._encoding.GetByteCount(header));

                        // Write the file data directly to the Stream, rather than serializing it to a string.
                        formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length);
                    }
                    else
                    {
                        string postData = string.Format(HttpMultipartPostReuest.GeneralParamContentDisposition, param.Key, param.Value);
                        formDataStream.Write(this._encoding.GetBytes(postData), 0, this._encoding.GetByteCount(postData));
                    }
                }

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

                // Dump the Stream into a byte[]
                formDataStream.Position = 0;
                byte[] formData = new byte[formDataStream.Length];
                formDataStream.Read(formData, 0, formData.Length);
                formDataStream.Close();

                return formData;
            }
        }

    }

        public class FileParameter
    {
        private const string DefaultContentType = "application/octet-stream";

        private readonly string _contentType;
        private readonly byte[] _file;
        private readonly string _fileName;

        public string ContentType { get { return this._contentType; } }
        public byte[] File { get { return this._file; } }
        public string FileName { get { return this._fileName; } }

        private FileParameter()
        {
            this._contentType = FileParameter.DefaultContentType;
        }

        public FileParameter(byte[] file) : this(file, FileParameter.DefaultContentType)
        {
        }

        public FileParameter(byte[] file, string filename) : this(file, filename, FileParameter.DefaultContentType)
        {
        }

        public FileParameter(string path, string fileName) : this()
        {
            this._file = FileParameter.LoadFile(path);
            this._fileName = fileName;
        }

        public FileParameter(string path, string fileName, string contentType)
            : this()
        {
            this._file = FileParameter.LoadFile(path);
            this._fileName = fileName;
            this._contentType = contentType;
        }

        public FileParameter(byte[] file, string fileName, string contentType)
        {
            this._file = file;
            this._fileName = fileName;
            if (!string.IsNullOrWhiteSpace(contentType))
            {
                this._contentType = contentType;
            }
            {
                this._contentType = FileParameter.DefaultContentType;
            }
        }

        private static byte[] LoadFile(string path)
        {
            byte[] data;
            // Read file data
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                data = new byte[fs.Length];
                fs.Read(data, 0, data.Length);
            }

            return data;
        }

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM