Curl -F эквивалент в C #

Я пытаюсь использовать объект HTTPClient в C # для отправки запроса на публикацию в API. Это команда CURL:

curl -X POST https://zzz.zzz.zzz/yyy -F Key=abcd -F [email protected]"audio.aac"

Я написал следующий код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.IO;
using System.Net.Http.Headers;

namespace Speech2Text
{
  class Program
  {
    static void Main(string[] args)
    {
        curl().Wait();
    }

    static async Task curl()
    {
        var client = new HttpClient();

        //Create List of KeyValuePairs
        List<KeyValuePair<string, string>> bodyProperties = new List<KeyValuePair<string, string>>();

        bodyProperties.Add(new KeyValuePair<string, string>("key", "abcd"));
        bodyProperties.Add(new KeyValuePair<string, string>("media", "@audio.aac"));

        var dataContent = new FormUrlEncodedContent(bodyProperties.ToArray());

        HttpResponseMessage response = await client.PostAsync("https://zzz.zzz.zzz/yyy", dataContent);

        HttpContent responseContent = response.Content;

        using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
        {
            Console.WriteLine(await reader.ReadToEndAsync());
        }
    }
  }
}

Но я продолжаю получать это:

{"code":400,"message":"Please use [media] for the media file field name in your POST request."}

Есть ли проблема в переменной dataContect или это что-то еще?

 user652277328 июл. 2016 г., 08:45
Попробуйте удалить "@" из "@ audio.aac"
 user652277328 июл. 2016 г., 08:29
Проблема на стороне сервера, а не на стороне клиента. Ваш код в порядке. Вы уже получили ответ JSON за это.
 Eris28 июл. 2016 г., 08:58
При использовании curl,@ хлебает содержимое файла. Вам нужно будет вручную открыть поток файлов и перетащить его в байтовый массив или что-то подобное
 shahram kalantari28 июл. 2016 г., 08:48
@x ... не сработало. Это имя файла, который я должен передать. Разве это не должен быть файловый объект или нечто подобное вместо строки?
 shahram kalantari28 июл. 2016 г., 08:27
@ w0lf Спасибо за ваш комментарий. Я использую тот же метод в моем коде выше, но я думаю, что он не захватывает параметры, которые я передаю в HTTP-запрос. Потому что покаmedia Параметр отправлен, он не понимает это.
 user652277328 июл. 2016 г., 08:55
Затем спросите сервер, что сервер действительно хочет ...: =) Вероятно, файл означает, что вы должны преобразовать его в base64 и поместить в параметр post.

Ответы на вопрос(1)

Решение Вопроса

При отправке сообщения POST важно, чтобы тип содержимого, отправляемый на сервер, действительно соответствовал ожидаемому. Вы можете легко проверить, что отправить с-trace вариант излокон:

curl -v --trace - -X POST http://localhost -F Key=abcd -F [email protected]"image.txt"

Когда вы запустите это, вы найдете где-то в первых нескольких строках это:

00b0: 63 6f 6e 74 69 6e 75 65 0d 0a 43 6f 6e 74 65 6e continue..Conten
00c0: 74 2d 54 79 70 65 3a 20 6d 75 6c 74 69 70 61 72 t-Type: multipar
00d0: 74 2f 66 6f 72 6d 2d 64 61 74 61 3b 20 62 6f 75 t/form-data; bou
00e0: 6e 64 61 72 79 3d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d ndary=----------
00f0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d ----------------
0100: 2d 2d 61 61 62 64 66 31 66 66 38 35 66 66 0d 0a --aabdf1ff85ff..
0110: 0d 0a                                           ..

Итак, curl отправляет Content-Typemultipart/form-data;

В вашем коде вы используете классFormUrlEncodedContent который заявляет в своем описании:

Контейнер для кортежей имя / значение, закодированных с использованием MIME-типа application / x-www-form-urlencoded.

Так что это не правильный Conent-Type.

Лучшее совпадениеMultipartFormDataContent потому что это заявляет:

Предоставляет контейнер для содержимого, закодированного с использованием MIME-типа multipart / form-data.

Когда найдены правильные классы, нам нужно только собрать контейнер:

var dataContent = new MultipartFormDataContent();
var keyValue = new ByteArrayContent( Encoding.ASCII.GetBytes("abcd") );
dataContent.Add(keyValue, "key");

using (var client = new HttpClient())
{
    // open your file
    using (var fs = File.OpenRead(@"c:\path\to\audio.acc"))
    {
        // create StreamContent from the file   
        var fileValue = new StreamContent(fs);
        // add the name and meta-data 
        dataContent.Add(fileValue, "media", "audio.acc");

        HttpResponseMessage response = await client.PostAsync(
                  "http://yoursite.org", 
                  dataContent);

        HttpContent responseContent = response.Content;

        using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
        {
            Console.WriteLine(await reader.ReadToEndAsync());
        }
    }
}

Запуск этого кода показывает вобманщик:

POST / HTTP/1.1
Content-Type: multipart/form-data; boundary="f7335f00-bc16-4518-ae7a-149491403792"
Host: yoursite.org
Content-Length: 1014
Expect: 100-continue
Connection: Keep-Alive

--f7335f00-bc16-4518-ae7a-149491403792
Content-Disposition: form-data; name=key

abcd
--f7335f00-bc16-4518-ae7a-149491403792
Content-Disposition: form-data; name=media; filename=audio.acc; filename*=utf-8''audio.acc

что больше соответствует выводу трассировки от curl.

 shahram kalantari05 авг. 2016 г., 01:55
Спасибо Рене за ваше тщательное решение.

Ваш ответ на вопрос