Как отправить HTTP POST запрос multipart / form-data из C # - PullRequest
14 голосов
/ 30 июля 2009

Какой самый простой способ отправить HTTP-запрос POST с типом содержимого multipart / form-data из C #? Должен быть лучший способ, чем создать мой собственный запрос.

Причина, по которой я спрашиваю, состоит в том, чтобы загрузить фотографии на Flickr с помощью этого API:

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

Ответы [ 6 ]

5 голосов
/ 20 октября 2013

Если вы используете .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();
        }

В противном случае, основываясь на ответе Райана, я скачал библиотеку и немного ее подправил.

  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;
                }
            }
        }
3 голосов
/ 08 июня 2015

Я сам не пробовал, но, похоже, в 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
    }
}

Попробуйте и дайте мне знать, как это происходит.

ура!

2 голосов
/ 06 ноября 2009

Я успешно справился с кодом, размещенным на aspnetupload.com . Я закончил тем, что сделал свою собственную версию их библиотеки UploadHelper, которая совместима с Compact Framework. Работает хорошо, похоже, делает именно то, что вам нужно.

1 голос
/ 30 июля 2009

Класс System.Net.WebClient может быть тем, что вы ищете. Проверьте документацию для WebClient.UploadFile, он должен позволить вам загрузить файл на указанный ресурс через одну из перегрузок UploadFile. Я думаю, что этот метод вы хотите использовать для публикации данных ...

Может использоваться как .... обратите внимание, это просто пример кода, не проверенный ...

WebClient webClient = new WebClient ();

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

Вот справочник MSDN, если вы заинтересованы.

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

Надеюсь, это поможет.

1 голос
/ 30 июля 2009

Во-первых, нет ничего плохого в чисто ручной реализации HTTP-команд с использованием .Net framework. Имейте в виду, что это фреймворк, и он должен быть довольно общим.

Во-вторых, я думаю, вы можете попробовать поискать реализацию браузера в .Net. Я видел этот , возможно, он охватывает проблему, о которой вы спрашивали. Или вы можете просто выполнить поиск " C # http put get post request ". Один из результатов приводит к несвободной библиотеке, которая может быть полезна ( Chilkat Http)

Если вам случится написать свой собственный каркас HTTP-команд поверх .Net - я думаю, что нам всем это понравится, если вы поделитесь им: -)

0 голосов
/ 29 января 2014

Обычно я считаю Скрипач лучшим инструментом для этой работы. Очень легко создавать запросы, и он даже генерирует некоторые заголовки для вас.

Fiddler - Как создать запрос

enter image description here

...