228

我使用这种语法来发布一个文件以及一些参数:

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

该文件大小约为 500K。首先,我看到传输端的内容长度为 254。后来服务器响应的内容长度为0。我哪里出错了?

这是命令的完整跟踪。

* 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
4

6 回答 6

327

以下语法为您修复它:

curl -v -F key1=value1 -F upload=@localfilename URL
于 2013-10-02T23:59:24.140 回答
25

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

例如

curl -v -F 'upload=@\"C:/myfile.txt\"' URL
于 2015-07-24T20:36:04.250 回答
19

这对我有用

curl --form file='@filename' URL

似乎当我给出这个答案时(4 多年前),我并没有真正理解这个问题,或者表单域是如何工作的。我只是根据我在不同场景中的尝试来回答,它对我有用。

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

解释

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

这可以上传二进制文件等。要强制“内容”部分成为文件,请在文件名前加上 @ 符号。要仅从文件中获取内容部分,请在文件名前加上符号 <。@ 和 < 之间的区别在于 @ 使文件作为文件上传附加在帖子中,而 < 生成文本字段并仅从文件中获取该文本字段的内容。

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

附录

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

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


您可能还对标题为:application/x-www-form-urlencoded 或 multipart/form-data?

我这样说是因为curl提供了其他上传文件的方式,但它们在标题中设置的内容类型不同。例如,该--data选项提供了一种将文件作为数据上传的类似机制,但使用不同的内容类型进行上传。

无论如何,这就是我想说的关于这个答案的全部内容,因为它开始得到更多的支持。我希望这有助于消除任何混淆,例如此答案与已接受答案之间的差异。真的没有,除了这个解释。

于 2016-03-10T08:30:18.077 回答
2

我很难将多部分 HTTP PUT 请求发送curl到 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 实现正在将 a\r\n--作为前缀添加到边界,因此将输入文件更改为

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

一切正常!

tl;博士

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

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

于 2019-03-01T07:50:21.560 回答
1

在 Windows 10,powershell 中的 curl 7.28.1 上,我发现以下内容对我有用:

$filePath = "c:\temp\dir with spaces\myfile.wav"
$curlPath = ("myfilename=@" + $filePath)
curl -v -F $curlPath URL
于 2016-09-16T18:41:15.960 回答
-2

也许这种形式有效

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

于 2021-12-07T17:03:05.147 回答