将 curl --form 转换为 C#

Convert curl --form to C#

我正在使用外部 api 并想使用 multipart/form-data 上传文件。 curl 中的工作解决方案是: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);
    }
}

然而它不起作用。 headers 和文件不同,所以我遇到了错误。

我写的代码和'works',但是附件无效,因为编码字节到字符串不正确。

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);

编辑: 来自 curl 请求的 headers:

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

第一个示例代码中的 headers:

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

我认为文件大小差异在这里是一个转移注意力的问题。

Web 服务器的常见做法是拒绝未指定用户代理的请求。尝试添加用户代理(甚至欺骗 curl 代理),如下所示:

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

第一个代码的问题是边界、文件headers 和输出headers 不同。我必须添加两个 Content-Type headers - 一个到我的文件,一个到输出。我无法添加正确的 headers 并删除错误的,因为我试图将 headers 添加到 multipart 而不是 multipart 内容。 如果您想将 header 添加到您的多部分内容中,您需要在 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 的 headers 几乎相同(缺少 Accept header,但我不需要它)。