使用curl POST multipart/form-data的正确方法是什么?

我用这个语法发布了一个带有一些参数的文件:

curl -v -include --form "key1=value1" --form upload=localfilename URL

文件大小约为500K。首先,我看到内容长度在传输端是254。之后,服务器响应的内容长度为0。 我哪里说错了?< / p >

下面是该命令的完整跟踪。

* Couldn't find host xxx.xxx.xxx.xxx in the _netrc file; using defaults
* About to connect() to xxx.xxx.xxx.xxx port yyyy (#0)
*   Trying xxx.xxx.xxx.xxx...
* Adding handle: conn: 0x4b96a0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x4b96a0) send_pipe: 1, recv_pipe: 0
* Connected to xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx) port yyyy (#0)
* POST /zzzzzz/UploadFile HTTP/1.1
* User-Agent: curl/7.32.0
* Host: xxx.xxx.xxx.xxx:yyyy
* Accept: */*
* Content-Length: 254
* Expect: 100-continue
* Content-Type: multipart/form-data; boundary=------------------------948a6137eef50079
*
* HTTP/1.1 100 Continue
* HTTP/1.1 100 Continue


* HTTP/1.1 200 OK
* HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
* Server: Apache-Coyote/1.1
* Server: Apache-Coyote/1.1
* Added cookie JSESSIONID="C1D7DD042E250211D9DEA82688876F88" for domain xxx.xxx.xxx.xxx, path /zzzzz/, expire 0
* Set-Cookie: JSESSIONID=C1D7DD042E250211D9DEA82688876F88; Path=/zzzzzz/;
* HttpOnly
* Set-Cookie: JSESSIONID=C1D7DD042E250211D9DEA82688876F88; Path=/zzzzzz/; HttpOnly
* Content-Type: text/html;charset=ISO-8859-1
Content-Type: text/html;charset=ISO-8859-1
* Content-Length: 0
* Content-Length: 0
* Date: Tue, 01 Oct 2013 11:54:24 GMT
* Date: Tue, 01 Oct 2013 11:54:24 GMT
* Connection #0 to host xxx.xxx.xxx.xxx left intact
290711 次浏览

下面的语法可以帮你解决这个问题:

curl -v -F key1=value1 -F upload=@localfilename URL

在Windows中使用curl上传文件,我发现路径需要转义双引号

如。

curl -v -F 'upload=@\"C:/myfile.txt\"' URL

这对我来说很管用

curl --form file='@filename' URL

似乎当我给出这个答案(4年多前)时,我并没有真正理解这个问题,或者表单字段是如何工作的。我只是根据我在另一种情况下的尝试来回答问题,这对我来说很有效。

因此,首先,OP所犯的唯一错误是在文件名之前没有使用@符号。其次,我的答案使用file=...只适用于我,因为我试图做上传的表单字段被称为file。如果您的表单字段名为其他名称,请使用该名称。

解释

curl 手册;在选项--form的描述下,它说:

允许上传二进制文件等。强制“内容” 部分要为文件,则在文件名前加上@符号。只是为了得到 文件的内容部分,在文件名前加上符号<。@和<的区别;那么@是a吗 文件得到 附件在帖子中作为文件上传,同时<创建一个文本框并从a中获取该文本框的内容 文件。< / p >

如果您尝试进行表单上传,则很可能希望使用@前缀来上传文件,而不是使用<前缀来上传文件的内容

齿顶高

现在我还必须补充一点,使用<符号时必须小心,因为在大多数unix shell中,<是输入重定向符号[巧合的是,它也会在<之前将给定文件的内容提供给程序的命令标准输入]。这意味着如果你没有正确地转义该符号或用引号将其括起来,你可能会发现你的curl命令没有按照你期望的方式运行。

同样,我也建议引用@符号。


你可能还会对另一个名为Application /x-www-form-urlencoded还是multipart/form-data?的问题感兴趣

我这么说是因为curl提供了其他上传文件的方法,但它们在头文件中的内容类型集上有所不同。例如,--data选项提供了类似的机制将文件作为数据上传,但使用不同的内容类型进行上传。

不管怎样,这就是我对这个答案想说的,因为它开始获得更多的赞。我希望这有助于消除任何混淆,例如这个答案和接受答案之间的区别。真的没有,除了这个解释。

在Windows 10, curl 7.28.1在powershell,我发现以下工作为我:

$filePath = "c:\temp\dir with spaces\myfile.wav"
$curlPath = ("myfilename=@" + $filePath)
curl -v -F $curlPath URL

我很难将一个包含curl的多部分HTTP PUT请求发送到Java后端。我只是试了试

curl -X PUT URL \
--header 'Content-Type: multipart/form-data; boundary=---------BOUNDARY' \
--data-binary @file

文件的内容是

-----------BOUNDARY
Content-Disposition: form-data; name="name1"
Content-Type: application/xml;version=1.0;charset=UTF-8


<xml>content</xml>
-----------BOUNDARY
Content-Disposition: form-data; name="name2"
Content-Type: text/plain


content
-----------BOUNDARY--

但我总是得到一个错误,边界是不正确的。经过一些Java后端调试后,我发现Java实现添加了\r\n--作为边界的前缀,所以在将我的输入文件更改为

                          <-- here's the CRLF
-------------BOUNDARY       <-- added '--' at the beginning
...
-------------BOUNDARY       <-- added '--' at the beginning
...
-------------BOUNDARY--     <-- added '--' at the beginning

一切正常!

博士tl;

在多部分边界内容的开头添加换行符(CRLF \r\n),并在边界的开头添加--,然后重试。

也许您正在向需要更改边界的Java后端发送请求。

也许这个形式可行

curl -X POST -d 'key1=value1&key2=value2' http://URL -H "Content-Type: application/x-www-form-urlencoded"

使用Smartbear Zephyr Scale(服务器版本),您可以通过以下方式将文件附加到测试周期:

curl -H "Authorization: Basic YkskfdygyzghhMg==" -X POST -H "Content-Type: multipart/form-data" https://jira/jira/rest/atm/1.0/testrun/TDLT-C32/attachments --form file="@file2.txt"

(返回{“id": 7099})

在file2.txt: Test Cycle中也有一个到测试计划的链接,以及一个到问题的链接。

{
"projectKey": "TDD",
"testPlanKey": "TDD-P1",
"name": "Bonjour chez vous, Le Prisonnier",
"issueKey": "TDLT-999"
}

我之所以发布这篇文章,是因为我无法从官方文件中找到答案:)