Загрузка файлов многочастных форм с помощью HttpClient - PullRequest
2 голосов
/ 11 февраля 2020

Я пытаюсь создать вложение с помощью Support Bee API, как описано здесь: https://supportbee.com/api#create_attachment

Я написал службу, которая использует HttpClient для создания и отправки запрос с использованием имени файла.

Если я проверю в Почтальоне, это будет успешно. Я использую form-data для тела и просто выбираю файл для загрузки из пользовательского интерфейса:

enter image description here

Это не работает, когда я пытаюсь загрузить его через мой HttpClient Сервис:

public async Task<string> CreateAttachmentAsync(string fileName)
{
    // "client" is HttpClient provided via D.I.

    MultipartFormDataContent content = new MultipartFormDataContent();
    content.Add(new StreamContent(new FileStream(fileName, FileMode.Open)), "files[]");

    using (HttpResponseMessage response = await client.PostAsync(
        "https://xxx.supportbee.com/attachments?auth_token=xxx",
        content))
    {
        string responseString = await response.Content.ReadAsStringAsync();

        return responseString;
    }
}

Это приводит к 500 Внутренняя ошибка сервера. Осматривая объект MultipartFormDataContent, я вижу, что его значения заголовка устанавливаются автоматически:

{Content-Type: multipart / form-data; border = "c9be3778-4de5-4460-9929-adcaa6bdda79" Content-Length: 164}

Я также попытался сначала прочитать файл в байтовый массив и использовать ByteArrayContent вместо StreamContent но безрезультатно. Ответ не дает ничего полезного, но так как запрос работает в Почтальоне, у меня должно быть что-то не так с моим кодом, но я не знаю, что еще попробовать.

Редактировать: я тестировал с Fiddler для сравнения успешный запрос почтальона к моему коду. Вот запрос к Почтальону:

POST https://xxx.supportbee.com/attachments?auth_token=xxx HTTP / 1.1 User-Agent: PostmanRuntime / 7.22.0 Принимать: / Cache-Control : no-cache Почтовый токен: f84d22fa-b4b1-4bf5-b183-916a786c6385 Хост: xx.supportbee.com Тип содержимого: multipart / form-data; border = -------------------------- 714700821471353664787346 Accept-Encoding: gzip, deflate, br Содержимое-длина: 241 Соединение: закрыть

---------------------------- 714700821471353664787346 Содержание-Расположение: форма-данные; имя = "файлы []"; filename = "sample.txt" Content-Type: text / plain

Содержит пример текста. ---------------------------- 714700821471353664787346 -

И неудачный запрос из моего кода:

POST https://xxx.supportbee.com/attachments?auth_token=xxx HTTP / 1.1 Хост: xxx.supportbee.com Принять: / Принять-кодирование: gzip, deflate, br Соединение: закрыть Контент- Тип: multipart / form-data; border = "ea97cbc1-70ea-4cc4-9801-09f5feffc763" Content-Length: 206

- ea97cbc1-70ea-4cc4-9801-09f5feffc763 Content-Disposition: form-data; имя = "файлы []"; имя файла = образец; имя файла * = utf-8''sample

Содержит пример текста. --ea97cbc1-70ea-4cc4-9801-09f5feffc763 -

Разница, которую я вижу, состоит в том, что отдельная часть в Postman имеет свой собственный заголовок Content-Type: text/plain для файла, а мой нет , Я не могу добавить это, потому что, если я пытаюсь content.Headers.Add("Content-Type", "text/plain"); Сбой «Не удается добавить значение, потому что заголовок« Content-Type »не поддерживает несколько значений.»

1 Ответ

1 голос
/ 12 февраля 2020

Во-первых, важно отметить, что ответ 500 похож на необработанное исключение, то есть это ошибка с их стороны и более или менее невозможно точно знать, что вы сделали неправильно. Я бы посоветовал сообщить об этом им, и, хотя я не знаком с Support Bee, я надеюсь, что у них есть хорошие люди поддержки, которые могут помочь вам устранить неполадки. :)

Но если вы хотите поиграть в угадайку, я согласен, что тонкие различия между вашим успешным звонком Почтальона и вашим кодом - хорошее место для начала. Для этого заголовка обратите внимание, что content является MultipartFormDataContent. Вы действительно хотите установить его для объекта StreamContent.

Кроме того, посмотрите заголовки запросов, которые отправляет почтальон, и посмотрите, включает ли Content-Disposition filename. Возможно, вам придется добавить это и в ваш код, если API ожидает его.

Вот как это сделать:

var fileContent = new StreamContent(File.OpenRead(path));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
content.Add(fileContent, "files[]", Path.GetFileName(path));

Если проблема не в этом, посмотрите на «raw "версия тела запроса в Postman, а также эти 11 заголовков запроса, и посмотрите, сможете ли вы найти что-то еще, что вам может не хватать.

...