How to submit a multipart/form-data HTTP POST request from C#

后端 未结 5 1452
予麋鹿
予麋鹿 2020-12-15 20:10

What is the easiest way to submit an HTTP POST request with a multipart/form-data content type from C#? There has to be a better way than building my own request.

T

相关标签:
5条回答
  • 2020-12-15 20:40

    If you are using .NET 4.5 use this:

    public string Upload(string url, NameValueCollection requestParameters, MemoryStream file)
            {
    
                var client = new HttpClient();
                var content = new MultipartFormDataContent();
    
                content.Add(new StreamContent(file));
                System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, string>> b = new List<KeyValuePair<string, string>>();
                b.Add(requestParameters);
                var addMe = new FormUrlEncodedContent(b);
    
                content.Add(addMe);
                var result = client.PostAsync(url, content);
                return result.Result.ToString();
            }
    

    Otherwise Based on Ryan's answer, I downloaded the library and tweaked it a bit.

      public class MimePart
            {
                NameValueCollection _headers = new NameValueCollection();
                byte[] _header;
    
                public NameValueCollection Headers
                {
                    get { return _headers; }
                }
    
                public byte[] Header
                {
                    get { return _header; }
                }
    
                public long GenerateHeaderFooterData(string boundary)
                {
                    StringBuilder sb = new StringBuilder();
    
                    sb.Append("--");
                    sb.Append(boundary);
                    sb.AppendLine();
                    foreach (string key in _headers.AllKeys)
                    {
                        sb.Append(key);
                        sb.Append(": ");
                        sb.AppendLine(_headers[key]);
                    }
                    sb.AppendLine();
    
                    _header = Encoding.UTF8.GetBytes(sb.ToString());
    
                    return _header.Length + Data.Length + 2;
                }
    
                public Stream Data { get; set; }
            }
    
            public string Upload(string url, NameValueCollection requestParameters, params MemoryStream[] files)
            {
                using (WebClient req = new WebClient())
                {
                    List<MimePart> mimeParts = new List<MimePart>();
    
                    try
                    {
                        foreach (string key in requestParameters.AllKeys)
                        {
                            MimePart part = new MimePart();
    
                            part.Headers["Content-Disposition"] = "form-data; name=\"" + key + "\"";
                            part.Data = new MemoryStream(Encoding.UTF8.GetBytes(requestParameters[key]));
    
                            mimeParts.Add(part);
                        }
    
                        int nameIndex = 0;
    
                        foreach (MemoryStream file in files)
                        {
                            MimePart part = new MimePart();
                            string fieldName = "file" + nameIndex++;
    
                            part.Headers["Content-Disposition"] = "form-data; name=\"" + fieldName + "\"; filename=\"" + fieldName + "\"";
                            part.Headers["Content-Type"] = "application/octet-stream";
    
                            part.Data = file;
    
                            mimeParts.Add(part);
                        }
    
                        string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
                        req.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary);
    
                        long contentLength = 0;
    
                        byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
    
                        foreach (MimePart part in mimeParts)
                        {
                            contentLength += part.GenerateHeaderFooterData(boundary);
                        }
    
                        //req.ContentLength = contentLength + _footer.Length;
    
                        byte[] buffer = new byte[8192];
                        byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
                        int read;
    
                        using (MemoryStream s = new MemoryStream())
                        {
                            foreach (MimePart part in mimeParts)
                            {
                                s.Write(part.Header, 0, part.Header.Length);
    
                                while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
                                    s.Write(buffer, 0, read);
    
                                part.Data.Dispose();
    
                                s.Write(afterFile, 0, afterFile.Length);
                            }
    
                            s.Write(_footer, 0, _footer.Length);
                            byte[] responseBytes = req.UploadData(url, s.ToArray());
                            string responseString = Encoding.UTF8.GetString(responseBytes);
                            return responseString;
                        }
                    }
                    catch
                    {
                        foreach (MimePart part in mimeParts)
                            if (part.Data != null)
                                part.Data.Dispose();
    
                        throw;
                    }
                }
            }
    
    0 讨论(0)
  • 2020-12-15 20:42

    I've had success with the code posted at aspnetupload.com. I ended up making my own version of their UploadHelper library which is compatible with the Compact Framework. Works well, seems to do exactly what you require.

    0 讨论(0)
  • 2020-12-15 20:47

    First of all, there's nothing wrong with pure manual implementation of the HTTP commands using the .Net framework. Do keep in mind that it's a framework, and it is supposed to be pretty generic.

    Secondly, I think you can try searching for a browser implementation in .Net. I saw this one, perhaps it covers the issue you asked about. Or you can just search for "C# http put get post request". One of the results leads to a non-free library that may be helpful (Chilkat Http)

    If you happen to write your own framework of HTTP commands on top of .Net - I think we can all enjoy it if you share it :-)

    0 讨论(0)
  • 2020-12-15 20:50

    The System.Net.WebClient class may be what you are looking for. Check the documentation for WebClient.UploadFile, it should allow you to upload a file to a specified resource via one of the UploadFile overloads. I think this is the method you are looking to use to post the data...

    It can be used like.... note this is just sample code not tested...

    WebClient webClient = new WebClient();

    webClient.UploadFile("http://www.url.com/ReceiveUploadedFile.aspx", "POST", @"c:\myfile.txt");

    Here is the MSDN reference if you are interested.

    http://msdn.microsoft.com/en-us/library/system.net.webclient.uploadfile.aspx

    Hope this helps.

    0 讨论(0)
  • 2020-12-15 20:55

    I have not tried this myself, but there seems to be a built-in way in C# for this (although not a very known one apparently...):

    private static HttpClient _client = null;
    
    private static void UploadDocument()
    {
        // Add test file 
        var httpContent = new MultipartFormDataContent();
        var fileContent = new ByteArrayContent(File.ReadAllBytes(@"File.jpg"));
        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "File.jpg"
        };
    
        httpContent.Add(fileContent);
        string requestEndpoint = "api/Post";
    
        var response = _client.PostAsync(requestEndpoint, httpContent).Result;
    
        if (response.IsSuccessStatusCode)
        {
            // ...
        }
        else
        {
            // Check response.StatusCode, response.ReasonPhrase
        }
    }
    

    Try it out and let me know how it goes.

    Cheers!

    0 讨论(0)
提交回复
热议问题