Отправка поля HTTP POST Multipart/form-data с использованием RestSharp

У меня возникают проблемы с использованием RestSharp для REST API, который мне нужно использовать для проекта, над которым я работаю. Запрос, который мне нужно отправить, состоит из трех частей: API-ключ заголовка, файл для загрузки и набор данных в формате JSON. API требует, чтобы часть данных была отправлена ​​с использованием имени поля формы «данные». По какой-то причине это вызывает проблемы, поскольку оно называет поле «данные» в теле запроса.

Код у меня выглядит следующим образом:

var request = new RestRequest(UPLOAD_DOC_URLSEGMENT, Method.POST)
{
    RequestFormat = DataFormat.Json,
    AlwaysMultipartFormData = true,
    JsonSerializer = new RestSharpJsonDotNetSerializer(customSerializer)
};

if (doc is DocA)
    request.AddParameter("data",doc as DocA,ParameterType.RequestBody);
    //request.AddBody(doc as DocA);
else
    request.AddParameter("data", doc as DocB,ParameterType.RequestBody);
    //request.AddBody(doc as DocB);

request.AddFile("file", doc.File.FullName);

Как видите, я пытался использовать как метод request.AddBody(doc), так и метод request.AddParameter(name, object, type). Ни один из них не отправляет данные должным образом, потому что я получаю ответ от сервера, в котором говорится, что необходимые параметры отсутствуют. Используя fiddler, я могу видеть двоичные данные, но никогда не вижу данные JSON с помощью обоих этих методов. Я просмотрел документацию RestSharp, но не могу найти ничего, что позволило бы мне указать конкретное имя «поля» как «данные» для тела данных формы, что, как я считаю, вызывает проблему, с которой я сталкиваюсь. . Что я здесь делаю неправильно?

РЕДАКТИРОВАТЬ: при дальнейшей проверке с помощью fiddler выясняется, что он вообще не добавляет мои данные JSON в тело HTTP-запроса. Однако с точкой останова прямо перед загрузкой (выполнение команды) я вижу, что все правильно сериализовано в списке параметров (и списке файлов). При проверке с помощью Fiddler я вижу двоичные данные файла, а затем границу multipart/form-data, а затем ничего. Я бы предположил, что здесь должны быть мои данные...


person JNYRanger    schedule 02.04.2014    source источник
comment
Я отредактировал ваш заголовок. См. Должны ли вопросы включать «теги» в свои заголовки?, если нет единого мнения, не следует.   -  person John Saunders    schedule 02.04.2014
comment
Извините, насчет этого! Только что прочитал эту статью, спасибо за редактирование.   -  person JNYRanger    schedule 02.04.2014
comment
Я тоже в поисках ответа. @JNYRanger ты уже нашел ответ ..? пожалуйста, дайте мне знать, если у вас есть решение. Заранее спасибо.   -  person Keval Langalia    schedule 26.08.2014
comment
@KevalLangalia Нет. В итоге я отказался от RestSharp и создал свой собственный REST-клиент, используя стандартный класс HttpWebRequest и JSON.NET.   -  person JNYRanger    schedule 27.08.2014
comment
для будущих посетителей эта проблема была исправлена ​​на RestSharp. ветка обсуждения: github.com/restsharp/RestSharp/issues/524   -  person kmonsoor    schedule 21.06.2016


Ответы (2)


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

Чтобы решить эту проблему, вам, возможно, придется немного поработать с обеих сторон коммуникации.

Чтобы отправить сообщение от клиента, вы делаете следующее:

new RestRequest("<Your URI>");
request.AddParameter("request", tokenRequest.ToJson());
request.AddFile("front", frontImage.CopyTo, "front");
request.AddFile("back", backImage.CopyTo, "back");
request.AddHeader("Content-Type", "multipart/form-data");

На стороне моего веб-сервиса я принимаю json в качестве аргумента метода и вручную получаю ссылку на файловые потоки:

public JsonResult MyService(StoreImageRequest request)
{
    var frontImage = HttpContext.Request.Files["front"].InputStream;
    var backImage = HttpContext.Request.Files["front"].InputStream;
}
person C Tierney    schedule 13.02.2015
comment
этот код работает для вас @C Tierney. Я хочу загрузить файл с некоторыми параметрами, но не могу заставить его работать. Я всегда получаю ответ с кодом состояния 0. {Базовое соединение было закрыто: при отправке произошла непредвиденная ошибка.} - person Adam; 21.06.2016
comment
tokenRequest, конечно, не определен и выдает исключение для того же... должна ли первая строка быть «var tokenRequest =», за которой следует строка? Или эта строка должна быть «var request =», у меня возникла эта проблема/исключение, и этот фрагмент кода для меня бесполезен. - person Traderhut Games; 07.12.2018
comment
токен был моим объектом json, который я хотел передать с ним, заднее изображение и переднее изображение также являются переменными кода выше этого. Мы токенизируем контрольные изображения, tokenRequest — это наш объект, который мы хотели передать вместе с файлами для создания набора данных, связанного с надежно сохраненными контрольными изображениями. Извините, что я не сделал это более ясным. - person C Tierney; 30.03.2020

Запрос из нескольких частей с телом JSON + части файла

Если ваш сервер может обрабатывать составные части с частями JSON body и Files, то

Код клиента:

        var req = new RestRequest(UPLOAD_DOC_URLSEGMENT, Method.POST);

        req.RequestFormat = DataFormat.Json;
        req.AddBody(doc);

        req.AddFileBytes("TestImage", Properties.Resources.TestImage, "TestImage.jpg");

        req.AddHeader("apikey", "MY-API-KEY");
        var resp = restClient.Execute<ApiResult>(req);

Код сервера:

На стороне сервера такой составной запрос должен обрабатываться как:

    [HttpPost]
    public JsonResult UploadDoc()
    {
        // This is multipart request. So we should get JSON from http form part:
        MyDocModel doc = JsonConvert.DeserializeObject<MyDocModel>(Request.Form[0]);
        
        foreach (string fileName in request.Files)
        {
            HttpPostedFileBase file = request.Files[fileName];
        }
person epox    schedule 18.07.2017
comment
Предыдущий ответ решает потребность, заявленную в теме, с помощью обходного пути tokenRequest.ToJson(). В этом ответе предлагается использовать req.RequestFormat = DataFormat.Json, который работает. - person epox; 31.07.2018