Я получаю неверный многочастный POST, когда пытаюсь отправить данные в удаленный API с помощью C# HttpClient

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

Я пытаюсь создать веб-сайт с помощью C# и ASP.NET Core 8. Мне нужно POST передать данные в удаленный API для загрузки моих видео (DoodStream API). Когда я пытаюсь опубликовать свои данные в API с помощью Postman, BurpSuite или простой HTML-формы, я получаю ответ об успешном завершении HTTP 200, и мои видео отображаются на панели управления.

Но когда я пытаюсь загрузить свои видео с помощью ASP.NET Core HttpClient, я получаю сообщение об ошибке:

HTTP 500 – неверный многочастный POST

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

Это функция загрузки:

public async Task<string> UploadDSAsync(string apiUrl, string apiKey, string filePath)
{
    using (var request = new HttpRequestMessage(HttpMethod.Post, $"{apiUrl}?key = {apiKey}"))
    {
        using (var form = new MultipartFormDataContent())
        {                  
            var ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36";
            request.Headers.Add("User-Agent", ua);

            var file = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));

            file.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("video/mp4");
            file.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
                    {
                        Name = "file",
                        FileName = Path.GetFileName(filePath)
                    };

            form.Add(new StringContent(apiKey), name: "api_key");
            form.Add(file, name: "file", Path.GetFileName(filePath));
                    
            request.Content = form;

            var response = _httpClient.Send(request);
            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsStringAsync();
        }
    }
}
[HttpPost]
[ValidateAntiForgeryToken]
[DisableRequestSizeLimit]
[Route("[controller]")] 
[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]
public async Task<IActionResult> Upload(IFormFile file)
{
    var url = $"https://doodapi.com/api/upload/server?key = {apiKey}";
    var res = await _doodStreamService.GetUploadServerAsync(url);
//res equals the url value, doostream provide us different urls for post videos.

    if (res == null)
    {
        return BadRequest(res);
    }

    if (file == null || file.Length == 0)
    {
        return BadRequest("Dosya seçilmedi.");
    }

    var filePath = Path.GetTempFileName().Replace(".tmp", ".mp4");

    using (var stream = System.IO.File.Create(filePath))
    {
        await file.CopyToAsync(stream);
    }

    var result = await _doodStreamService.UploadDSAsync(res, apiKey, filePath);

    // Geçici dosyayı silin
    System.IO.File.Delete(filePath);

    return Ok(result);
}

Я хочу показать вам успешный HTTP-запрос Post.

POST /upload/01?key=mykey HTTP/1.1
Host: io274l.video-delivery.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:127.0) Gecko/20100101 Firefox/127.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------329310205013466975143905415842
Content-Length: 2789881
Origin: http://127.0.0.1:5500
Referer: http://127.0.0.1:5500/
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
Priority: u=1
Te: trailers
Connection: keep-alive

-----------------------------329310205013466975143905415842
Content-Disposition: form-data; name = "api_key"

182790a84ywqe32dp5y9ty
-----------------------------329310205013466975143905415842
Content-Disposition: form-data; name = "file"; filename = "aaa.mp4"
Content-Type: video/mp4

ftypmp42mp42isomavc1Ímoovxmvhdâ$â$X@Ätrakhtkhdâ$â$@8,edts$elst»(mdia,mdhdâ$â$]ÀÃØUÄ:hdlrvideVimeo Artax Video Handlerºminfvmhd$dinfdrefurl zstbl²stsd¢avc18HH
AVC Codingÿÿ9avcCd*ÿágd*¬Ùx'å  pã3@hé{,ýøøcolrnclxstts8é`cttsê»ÒÒÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒ¤Ò»ÒÒÒÒÒÒÒv»éÒv»éÒv»éÒÒÒÒÒv»éÒ¤ÒÒÒÒÒÒÒ¤Ò»ÒÒÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒv»éÒv»éÒv»éÒÒÒÒÒ¤Ò»ÒÒÒÒÒÒÒv»éÒv»éÒv»éÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒ¤Ò¤é¤é¤é¤é¤é¤é¤é»é$stssIÙ!stscôstsz8õDE©Ç
3

MORE VİDEO BYTES
...
...

----------------------------329310205013466975143905415842--

Он возвращает данные http 200 и JSON о загруженном видео.

И это другой мой запрос в ASP.NET Core, но теперь он возвращает http 500 и завершается с ошибкой.

POST /upload/01?key=myapikey HTTP/1.1
Host: yu1073k.video-delivery.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
traceparent: 00-612759c4039f28f75b3b845b2154898f-c618443035899a1d-00
Content-Type: multipart/form-data; boundary = "a0cc5a75-c0d5-4328-8007-6abab10c2ee5"
Content-Length: 2789859
Connection: keep-alive

--a0cc5a75-c0d5-4328-8007-6abab10c2ee5
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=api_key

182790a84ywqe32dp5y9ty
--a0cc5a75-c0d5-4328-8007-6abab10c2ee5
Content-Type: video/mp4
Content-Disposition: form-data; name=file; filename=tmputfimX.mp4

ftypmp42mp42isomavc1Ímoovxmvhdâ$â$X@Ätrakhtkhdâ$â$@8,edts$elst»(mdia,mdhdâ$â$]ÀÃØUÄ:hdlrvideVimeo Artax Video Handlerºminfvmhd$dinfdrefurl zstbl²stsd¢avc18HH
AVC Codingÿÿ9avcCd*ÿágd*¬Ùx'å  pã3@hé{,ýøøcolrnclxstts8é`cttsê»ÒÒÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒ¤Ò»ÒÒÒÒÒÒÒv»éÒv»éÒv»éÒÒÒÒÒv»éÒ¤ÒÒÒÒÒÒÒ¤Ò»ÒÒÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒv»éÒv»éÒv»éÒÒÒÒÒ¤Ò»ÒÒÒÒÒÒÒv»éÒv»éÒv»éÒÒÒÒÒ¤Òv»éÒÒÒÒÒÒÒ¤Ò¤é¤é¤é¤é¤é¤é¤é»é$stssIÙ!stscôstsz8õDE©Ç
3!À}â`>ö´À$ÏDò ßþ!KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK¿BMORE BYTES
...

--a0cc5a75-c0d5-4328-8007-6abab10c2ee5--

Кстати, в обоих http запросах видеобайты верные, проблема не в этом.

Документация по локальной загрузке API Doodstream

Я пробовал несколько раз с burpsuite и почтальоном, он возвращает http 200.

Я хочу загрузить его с помощью функции UploadDSAsync.

Вы пробовали использовать SendAsync httpclient и ждали его?

SoftwareDveloper 01.07.2024 19:34

Да, не сработало.

Mert 01.07.2024 19:38

Попробуйте использовать Upload([FromBody]MultipartFormDataContent контент) вместо IFormFile.

Mykhailo Svyrydovych 01.07.2024 22:27

Я попробовал, не получилось.

Mert 02.07.2024 01:27

Когда вы говорите "not worked", что произошло на самом деле? Вызывает ли это какую-либо ошибку? или что у тебя есть?

Md Farid Uddin Kiron 02.07.2024 02:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я пытаюсь создать веб-сайт с помощью C# и ASP.NET Core 8. Мне следует POST-данные в удаленный API для загрузки моих видео (DoodStream API). Когда я пытаюсь опубликовать свои данные в API с помощью Postman, BurpSuite или простая html-форма, я получаю ответ об успешном завершении HTTP 200 и свои видео. видны на приборной панели.

Но когда я пытаюсь загрузить свои видео с помощью HttpClient ASP.NET Core, я получаю ошибку:

HTTP 500 – неверный многочастный POST

Основываясь на вашем общем фрагменте кода и описании, я попытался воспроизвести вашу ошибку и обнаружил несколько проблем в вашем коде.

Прежде всего, я обнаружил, что Content-Disposition header для части файла (файла) мог быть отформатирован неправильно. Правильный формат должен быть «form-data; name="file"; filename="filename.ext"».

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

Самое главное, вы добавляете StringContent и ByteArrayContent в MultipartFormDataContent.

Но проблема заключается в том, как вы добавляете содержимое файла (файл) в MultipartFormDataContent (форму). Правильный способ добавить ByteArrayContent в MultipartFormDataContent — просто form.Add(file).

Наконец, в UploadDSAsync вы использовали Path.GetFileName(filePath) при добавлении файла в форму, но я подозреваю, что такое использование может быть неправильным. Правильный способ добавления файла в MultipartFormDataContent form.Add(file, "file", Path.GetFileName(filePath)).

Чтобы это исправить, я попробовал следующим образом и отправил файл mp4 в соответствии с API, используя метод UploadDSAsync.

Давайте посмотрим на практике:

Метод обработки MultipartFormDataContent:

private async Task<string> UploadDSAsync(string url, string filePath)
{
    var httpClient = _httpClientFactory.CreateClient();
    var ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36";

    using (var request = new HttpRequestMessage(HttpMethod.Post, url))
    {
        request.Headers.Add("User-Agent", ua);
        using (var form = new MultipartFormDataContent())
        {
            var fileContent = new ByteArrayContent(await System.IO.File.ReadAllBytesAsync(filePath));

            fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
            fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
            {
                Name = "file",
                FileName = Path.GetFileName(filePath)
            };

            form.Add(fileContent);

            request.Content = form;

            var response = await httpClient.SendAsync(request);
            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsStringAsync();
        }
    }
}

Примечание. Поскольку я тестирую в локальной среде, я удалил APIKey.

Выход:

Примечание. Пожалуйста, обратитесь к этому официальному документу для получения дополнительной помощи и образца.

Большое спасибо. Ты герой. Я решил свою проблему, ваш ответ мне очень помог.

Mert 03.07.2024 21:54

Спасибо @Mert за ваш ответ и рад узнать, что вам удалось решить проблему.

Md Farid Uddin Kiron 04.07.2024 10:21

Другие вопросы по теме