如何从 C# 提交多部分/表单数据 HTTP POST 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1203811/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:50:19  来源:igfitidea点击:

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

c#.nethttppostmultipartform-data

提问by Jesse Weigert

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.

从 C# 提交具有 multipart/form-data 内容类型的 HTTP POST 请求的最简单方法是什么?必须有比构建我自己的请求更好的方法。

The reason I'm asking is to upload photos to Flickr using this api:

我问的原因是使用这个 api 将照片上传到 Flickr:

http://www.flickr.com/services/api/upload.api.html

http://www.flickr.com/services/api/upload.api.html

采纳答案by Ron Klein

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.

首先,使用 .Net 框架纯手动实现 HTTP 命令没有任何问题。请记住,它是一个框架,它应该是非常通用的。

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 (ChilkatHttp)

其次,我认为您可以尝试在 .Net 中搜索浏览器实现。我看到了这个,也许它涵盖了您询问的问题。或者你可以只搜索“ C# http put get post request”。其中一个结果导致了一个可能有用的非免费库(ChilkatHttp)

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 :-)

如果您碰巧在 .Net 之上编写了自己的 HTTP 命令框架 - 我想如果您分享它,我们都可以享受它:-)

回答by Wil P

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...

System.Net.WebClient 类可能正是您要找的。检查 WebClient.UploadFile 的文档,它应该允许您通过 UploadFile 重载之一将文件上传到指定的资源。我认为这是您希望用来发布数据的方法...

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

它可以像......一样使用......注意这只是未经测试的示例代码......

WebClient webClient = new WebClient();

WebClient webClient = new WebClient();

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

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

Here is the MSDN reference if you are interested.

如果您有兴趣,这里是 MSDN 参考。

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

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

Hope this helps.

希望这可以帮助。

回答by Ryan Barton

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.

我在aspnetupload.com 上发布的代码取得了成功。我最终制作了自己的 UploadHelper 库版本,该版本与 Compact Framework 兼容。效果很好,似乎完全符合您的要求。

回答by David Silva Smith

If you are using .NET 4.5 use this:

如果您使用的是 .NET 4.5,请使用:

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.

否则,根据 Ryan 的回答,我下载了该库并对其进行了一些调整。

  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;
                }
            }
        }

回答by NoOne

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...):

我自己没有尝试过这个,但在 C# 中似乎有一种内置的方法(尽管显然不是一个非常知名的方法......):

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!

干杯!