Конвертировать curl --form в C # - PullRequest
0 голосов
/ 30 мая 2019

Я работаю с внешним API и хочу загрузить файл, используя multipart / form-data. Рабочий раствор в скручивании: curl --form file=@./fileName.mp4 "http://page.com"

Согласно https://curl.olsh.me/. Код, который я ищу:

using (var httpClient = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://page.com/"))
        {
            var multipartContent = new MultipartFormDataContent();
            multipartContent.Add(new  ByteArrayContent(File.ReadAllBytes("./fileName.mp4")), "file", Path.GetFileName("./fileName.mp4"));
        request.Content = multipartContent; 

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

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

Код, который я написал и «работает», но вложение недопустимо, потому что кодирование байтов в строку некорректно.

var webClient = new HttpClient();
            webClient.DefaultRequestHeaders.ExpectContinue = true;
            string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
            var fileData = Encoding.ASCII.GetString(System.IO.File.ReadAllBytes(pathToFile));
            var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, "fileName", "application/octet-stream", fileData);
            var content = new StringContent(package);
            content.Headers.Remove("Content-Type");
            content.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
            content.Headers.Remove("Content-Length");
            content.Headers.Add("Content-Length", package.Length.ToString());
await webClient.PostAsync(address, content);

Edit: Заголовки из curl запроса:

POST http://page.com/ HTTP/1.1
Host: page.com
User-Agent: curl/7.55.1
Accept: */*
Connection: Keep-Alive
Content-Length: 1703578
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------1a538744c5619c1e

--------------------------1a538744c5619c1e
Content-Disposition: form-data; name="file"; filename="cst.mp4"
Content-Type: application/octet-stream

Заголовки из первого примера кода:

POST http://page.com/ HTTP/1.1
Content-Type: multipart/form-data; boundary="735b20d4-4de4-46fb-8293-2c2e996ce180"
Content-Length: 1703552
Host: page.com

--735b20d4-4de4-46fb-8293-2c2e996ce180
Content-Disposition: form-data; name=file; filename=cst.mp4; filename*=utf-8''cst.mp4

Ответы [ 2 ]

0 голосов
/ 02 июня 2019

Проблема с первым кодом заключается в том, что границы, заголовки файлов и выходные заголовки отличаются. Мне пришлось добавить два заголовка Content-Type - один в мой файл и один в выходной. Мне не удалось добавить правильные заголовки и удалить неправильные, потому что я пытался добавить заголовки в составное, а не составное содержимое. Если вы хотите добавить заголовки к вашему составному контенту, вам нужно сделать это на HttpContent. Рабочий раствор:

string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
            using (var httpClient = new HttpClient())
            {
                using (var request = new HttpRequestMessage(new HttpMethod("POST"), address))
                {
                    httpClient.DefaultRequestHeaders.Add("User-Agent", userAgentName);
                    httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
                    httpClient.DefaultRequestHeaders.ExpectContinue = true;
                    var multipartContent = new MultipartFormDataContent(boundary);
                    multipartContent.Headers.Remove("Content-Type");
                    multipartContent.Headers.Add("Content-Type", "multipart/form-data; boundary="+boundary);
                    var bcd = new ByteArrayContent(System.IO.File.ReadAllBytes(path));
                    bcd.Headers.Clear();
                    bcd.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\""+fileName+"\"");
                    bcd.Headers.Add("Content-Type", "application/octet-stream");
                    multipartContent.Add(bcd, "file", fileName);
                    request.Content = multipartContent;

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

Теперь заголовки из curl и HttpClient практически совпадают (заголовок Accept отсутствует, но мне он не нужен).

0 голосов
/ 31 мая 2019

Я думаю, что здесь разница в размере файла - красная сельдь.

Обычная практика для веб-серверов - запрещать запросы, в которых не указан пользовательский агент.Попробуйте добавить пользовательский агент (или даже подделать агент curl), как показано ниже:

webClient.DefaultRequestHeaders.Add("User-Agent", "curl/7.55.1");
...