cURL 中 -d 和 --data 有什么区别?
-d 和 --data 是什么关系?
-d 和 --data 是同一个参数的短格式和长格式,功能完全等价,没有任何行为差异。
bash# 下面两条命令完全等价 curl -d "name=value" https://api.example.com curl --data "name=value" https://api.example.com
cURL 的大多数参数都有这种短/长格式对应关系,比如 -X 和 --request、-H 和 --header。选择哪种写法纯属个人偏好:命令行简短操作用 -d,脚本中为了可读性用 --data。
cURL 有哪些数据发送方式?
-d 只是 cURL 数据发送家族中的一个。不同参数对应不同的数据处理逻辑和 Content-Type:
| 参数 | 数据处理方式 | 默认 Content-Type | 典型场景 |
|---|---|---|---|
-d / --data | 发送数据,@ 读取文件并去除回车换行 | application/x-www-form-urlencoded | 表单提交、API 调用 |
--data-ascii | 与 -d 完全相同 | application/x-www-form-urlencoded | 明确语义时使用 |
--data-binary | 发送原始数据,@ 读取文件不做任何处理 | 不自动设置 | 二进制文件、保留换行的文本 |
--data-urlencode | 自动对特殊字符做 URL 编码 | application/x-www-form-urlencoded | 参数含空格或特殊字符 |
--data-raw | 原样发送,@ 不被解析为文件路径 | application/x-www-form-urlencoded | 数据内容本身含 @ 符号 |
-F / --form | multipart/form-data 编码 | multipart/form-data | 文件上传、混合表单 |
--json | 发送 JSON,自动设置 Content-Type | application/json | REST API JSON 交互 |
-d 和 -F 的核心区别是什么?
这是面试高频追问点。-d 发送的是整体编码的请求体,-F 发送的是分段编码的请求体:
bash# -d:整个请求体作为一个 URL 编码字符串 curl -d "name=张三&age=25" https://api.example.com/form # 请求体:name=张三&age=25 # Content-Type: application/x-www-form-urlencoded # -F:每个字段单独编码,用 boundary 分隔 curl -F "name=张三" -F "file=@photo.jpg" https://api.example.com/upload # Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
简单记忆:纯键值对用 -d,涉及文件上传用 -F。两者不能混用——如果同时指定,cURL 只会使用后出现的那个。
如何发送 JSON 数据?
用 -d 配合手动设置 Content-Type,或者直接用 --json(cURL 7.82.0+):
bash# 方式一:-d + 手动设置 Header(兼容性最好) curl -X POST https://api.example.com/users \ -H "Content-Type: application/json" \ -d '{"name":"张三","age":25}' # 方式二:--json(7.82.0+,自动设置 Content-Type) curl --json '{"name":"张三","age":25}' https://api.example.com/users
注意:-d 不会自动转义或编码 JSON 中的特殊字符。如果 JSON 数据来自用户输入或文件,务必确保格式合法:
bash# 从文件读取 JSON curl -X POST https://api.example.com/users \ -H "Content-Type: application/json" \ -d @payload.json
--data-binary 和 -d 读取文件有什么不同?
这是另一个容易踩坑的点。当用 @ 从文件读取数据时,-d 会静默去除回车符和换行符,--data-binary 则原样发送:
bash# 准备一个包含换行的文件 # data.txt 内容: # line1 # line2 # line3 # -d 读取文件:换行被去除,数据变成 "line1line2line3" curl -d @data.txt https://api.example.com # --data-binary 读取文件:换行完整保留 curl --data-binary @data.txt https://api.example.com
发送 JSON、XML、二进制文件时,永远用 --data-binary 而不是 -d,否则数据可能被静默破坏。
--data-urlencode 和 --data-raw 什么时候用?
bash# --data-urlencode:参数值含空格或特殊字符时 curl --data-urlencode "query=hello world!" https://api.example.com/search # 实际发送:query=hello%20world%21 # --data-raw:数据内容本身包含 @ 符号,不想被解释为文件路径 curl --data-raw "@channel notify" https://api.example.com/webhook # 发送的就是字面量 @channel notify,不会去找叫 channel 的文件
多个 -d 参数如何处理?
多次使用 -d 时,cURL 会用 & 将各段拼接起来:
bashcurl -d "name=张三" -d "email=zhangsan@example.com" https://api.example.com/form # 等价于 curl -d "name=张三&email=zhangsan@example.com" https://api.example.com/form
也可以混合使用不同数据参数,但要注意各自的编码规则:
bashcurl -d "title=测试" \ --data-urlencode "content=Hello World!" \ --data-binary @attachment.pdf \ https://api.example.com/mixed
常见踩坑点
1. 使用 -d 就隐含了 POST 请求
-d 会自动将请求方法设为 POST,不需要额外写 -X POST。如果你同时写了 -X GET -d "data",cURL 会发送一个带 body 的 GET 请求——这在大多数服务端会被忽略或拒绝。
2. Content-Type 需要自己管
-d 默认设置 application/x-www-form-urlencoded。如果你要发 JSON 却忘记加 -H "Content-Type: application/json",服务端可能按表单解析导致 400 错误。
3. @ 符号的双重含义
-d @filename 读取文件内容,-d @- 从标准输入读取。如果你的数据本身包含 @,必须用 --data-raw。
4. -d 和 -F 不能混用
一个请求中只能选一种数据提交方式。如果两者都写了,cURL 只认后出现的那个,前面的会被静默忽略。