为什么使用 cURL 上传的文件包含请求的一部分 header - 如边界,Content-Type - 在文件的开头?

Why do files uploaded with cURL contain part of the request header - like boundary, Content-Type - at the beginning of the file?

我正在尝试使用 cURL 命令行实用程序将文件上传到文件托管服务。起初,我使用 Chromium 浏览器上传了一个文件,打开了 Web 开发人员控制台:在网络选项卡中,我查找了合适的行,然后单击 "copy all as curl"。我模仿了相同的请求 - 在正确登录并附加保存的 cookie 文件后 - 使用 cURL,但是当我下载上传的文件时,不幸的是,文件内容总是以我发送的 HTTP headers 的几行开头显式地(使用 -H 设置,如 Content-Type),或由 cURL 隐式添加(如边界)。

文件内容开头示例:

--------------------------1dbea6717e57a1ab
Content-Disposition: attachment; name="files[]"; filename="data.bin"
Content-Type: application/octet-stream

<...binary file data then...>

其中行结尾是 CR/LF(在十六进制查看器中是 0D0A),并且双 CR/LF 0D0A0D0A 是不需要的 header。

什么会导致这种奇怪的行为?服务器端程序似乎无法将二进制文件数据与 header 行分开。也许我应该手动设置边界或仅使用 LF (line-feed, 0A) 作为 header 的行尾?我找不到这样的 cURL 选项,它可以设置分隔 header 行的字符 (CR/LF <-> LF)。

我上传时使用的cURL命令:

curl 'https://example.com/upload' -H 'Origin: https://example.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9,hu;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36' -H 'Content-Type: application/octet-stream' -H 'Accept: */*' -H 'Referer: https://example.com/' -b cookie.txt -H 'Connection: keep-alive' -F "files[]=@data.bin" --compressed -L

如果我使用该服务的网络上传器 - 一些 JS 库 - 文件当然没问题。

如果我使用这个命令,那么它基本上可以工作,问题是,服务器上的文件大小将为零。但是当我下载文件时,它完好无损,md5sum 通过了。当我使用网络上传器时也不会发生这种情况,在这种情况下服务器上的文件大小再次正常。

curl 'https://example.com/upload' -H 'Origin: https://example.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9,hu;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36' -H 'Accept: */*' -H 'Referer: https://example.com/'  -H 'Connection: keep-alive' -b cookie.txt -F "files[]=@data.bin;type=application/octet-stream" --compressed -L

It seems that the server side program can't separate the binary file data from the header lines

是的,很可能是这样,服务器端程序不理解 multipart/form-data 格式,并认为多部分 headers 是实际文件的一部分。这表明服务器希望您在请求 body 中上传原始文件。要让 curl 在请求 body 中上传原始文件,请改用 --data-binary @filename

https://example.com/upload的文档应该说明应该如何上传文件。