简体   繁体   English

使用 curl 发布多部分/表单数据的正确方法是什么?

[英]What is the right way to POST multipart/form-data using curl?

I used this syntax to post a file along with some parameters:我使用这种语法来发布一个文件以及一些参数:

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

The file is around 500K in size.该文件大小约为 500K。 First of all, I see content length to be 254 on the transmit side.首先,我看到传输端的内容长度为 254。 Later the server response's content length is 0. Where am I going wrong?后来服务器响应的内容长度为0。我哪里出错了?

Here is the complete trace of the command.这是命令的完整跟踪。

* 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

以下语法为您修复它:

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

to upload a file using curl in Windows I found that the path requires escaped double quotes在 Windows 中使用 curl 上传文件我发现路径需要转义双引号

eg例如

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

This is what worked for me这对我有用

curl --form file='@filename' URL

It seems when I gave this answer ( 4+ years ago ), I didn't really understand the question, or how form fields worked.似乎当我给出这个答案时( 4 年多以前),我并没有真正理解这个问题,或者表单字段是如何工作的。 I was just answering based on what I had tried in a difference scenario, and it worked for me.我只是根据我在不同场景中的尝试来回答,它对我有用。

So firstly, the only mistake the OP made was in not using the @ symbol before the file name.所以首先,OP 犯的唯一错误是没有在文件名前使用@符号。 Secondly, my answer which uses file=... only worked for me because the form field I was trying to do the upload for was called file .其次,我使用file=...答案只对我有用,因为我尝试上传的表单字段被称为file If your form field is called something else, use that name instead.如果您的表单字段被称为其他名称,请改用该名称。

Explanation说明

From the curl manpages ;来自curl联机帮助页 under the description for the option --form it says:在选项--form的描述下,它说:

This enables uploading of binary files etc. To force the 'content' part to be a file, prefix the file name with an @ sign.这允许上传二进制文件等。要强制“内容”部分成为文件,请在文件名前加上 @ 符号。 To just get the content part from a file, prefix the file name with the symbol <.要仅从文件中获取内容部分,请在文件名前加上符号 <。 The difference between @ and < is then that @ makes a file get attached in the post as a file upload, while the < makes a text field and just get the contents for that text field from a file. @ 和 < 之间的区别在于 @ 使文件作为文件上传附加到帖子中,而 < 生成文本字段并仅从文件中获取该文本字段的内容。

Chances are that if you are trying to do a form upload, you will most likely want to use the @ prefix to upload the file rather than < which uploads the contents of the file.很有可能,如果您尝试进行表单上传,您很可能希望使用@前缀上传文件,而不是<上传文件的内容

Addendum附录

Now I must also add that one must be careful with using the < symbol because in most unix shells, < is the input redirection symbol [which coincidentally will also supply the contents of the given file to the command standard input of the program before < ] .现在我还必须补充一点,使用<符号时必须小心,因为在大多数 unix shell 中, <是输入重定向符号[巧合的是,它也会在<之前将给定文件的内容提供给程序的命令标准输入] . This means that if you do not properly escape that symbol or wrap it in quotes, you may find that your curl command does not behave the way you expect.这意味着,如果您没有正确地转义该符号或将其包裹在引号中,您可能会发现curl命令的行为与您期望的方式不同。

On that same note, I will also recommend quoting the @ symbol.同样,我还建议引用@符号。


You may also be interested in this other question titled: application/x-www-form-urlencoded or multipart/form-data?您可能还对另一个问题感兴趣: application/x-www-form-urlencoded 或 multipart/form-data?

I say this because curl offers other ways of uploading a file, but they differ in the content-type set in the header.我这样说是因为curl提供了其他上传文件的方法,但它们在标题中设置的内容类型不同。 For example the --data option offers a similar mechanism for uploading files as data, but uses a different content-type for the upload.例如,-- --data选项提供了一种类似的将文件作为数据上传的机制,但使用不同的内容类型进行上传。

Anyways that's all I wanted to say about this answer since it started to get more upvotes.无论如何,这就是我想说的关于这个答案的全部内容,因为它开始获得更多的支持。 I hope this helps erase any confusions such as the difference between this answer and the accepted answer.我希望这有助于消除任何混淆,例如此答案与已接受答案之间的差异。 There is really none, except for this explanation.真的没有,除了这个解释。

I had a hard time sending a multipart HTTP PUT request with curl to a Java backend.我很难将带有curl的多部分 HTTP PUT 请求发送到 Java 后端。 I simply tried我只是试过

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

and the content of the file was并且文件的内容是

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

but I always got an error that the boundary was incorrect.但我总是收到一个错误,说边界不正确。 After some Java backend debugging I found out that the Java implementation was adding a \\r\\n-- as a prefix to the boundary, so after changing my input file to经过一些 Java 后端调试后,我发现 Java 实现添加了一个\\r\\n--作为边界的前缀,因此在将我的输入文件更改为

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

everything works fine!一切正常!

tl;dr tl;博士

Add a newline (CRLF \\r\\n ) at the beginning of the multipart boundary content and -- at the beginning of the boundaries and try again.在多部分边界内容的开头和--在边界的开头添加换行符 (CRLF \\r\\n ),然后重试。

Maybe you are sending a request to a Java backend that needs this changes in the boundary.也许您正在向需要边界更改的 Java 后端发送请求。

On Windows 10, curl 7.28.1 within powershell, I found the following to work for me:在 Windows 10 上,powershell 中的 curl 7.28.1,我发现以下内容对我有用:

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

Maybe this form work也许这种形式有效

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

With Smartbear Zephyr Scale, server version, you would attach a file to a Test Cycle this way:使用 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"

(returns {"id":7099}) (返回 {"id":7099})

where in file2.txt: Test Cycle has also a link to a test plan, and a link to an issue.在 file2.txt 中的位置:测试周期还有一个指向测试计划的链接和一个指向问题的链接。

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

I'm posting this since unable to find that out from official documentation:)我发布这个是因为无法从官方文档中找到它:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM