news 2026/9/9 19:38:20

curl 命令 `--data-binary` 完全指南:按原样 POST 二进制数据、保留换行与空字节的底层原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
curl 命令 `--data-binary` 完全指南:按原样 POST 二进制数据、保留换行与空字节的底层原理

curl 命令--data-binary完全指南:按原样 POST 二进制数据、保留换行与空字节的底层原理

【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl

--data-binary是 curl(命令行工具与 libcurl 传输库)用于 HTTP POST 时"按字节原样提交数据"的关键选项:它不做任何额外加工、不剥离换行与回车、也不过滤空字节。本文以仓库中该选项的官方说明 docs/cmdline-opts/data-binary.md 为骨架,结合 curl 源码中的参数解析链路,为你梳理它的语法、与--data/--data-raw/--data-urlencode的取舍、Content-Type 设置技巧,以及"数据如何从命令行进入请求体"的实现细节。

选项速览:--data-binary是什么

在 curl 中,所有以--data开头的系列选项都用于向服务器发送数据。--data-binary的官方定义极其精简,却也点出了它与其他选项最本质的差异:

Post data exactly as specified with no extra processing whatsoever. (完全按给定内容发送数据,不做任何额外处理。)

从该选项的元数据定义(见 docs/cmdline-opts/data-binary.md 开头的 front-matter)可以得到如下事实表:

属性取值说明
长选项--data-binary无短选项别名
参数<data>数据本体,或@filename/@-
帮助文本HTTP POST binary data工具内置帮助同样如此描述
适用协议HTTP--data(HTTP + MQTT)不同,仅限 HTTP
分类http post upload属于 HTTP 表单提交 / 上传家族
引入版本7.2相当古老的选项,早已是稳定行为
Multi 属性append可重复使用,多次指定的数据会拼接

curl 命令行工具内置的帮助列表也做了同步维护,可在 src/tool_listhelp.c 中看到--data-binary <data>的条目。

核心差异:什么叫做"不做任何额外处理"

理解--data-binary的最好方式,是与同族的其他选项对照。curl 对@前缀和换行/空字节的处理在各选项间并不一致,这正是选择--data-binary的真正理由。

--data的对比:保留换行、回车与二进制

官方文档>curl --data-binary @filename $URL

一个更接近真实用途的示例——上传 JSON 文件并显式声明媒体类型:

curl --data-binary @data.json \ -H "Content-Type: application/json" \ https://api.example.com/v1/ingest

Content-Type:默认表单编码,如何切换为任意二进制

--data相同,--data-binary默认发送给服务器的 Content-Type 是application/x-www-form-urlencoded。这是历史兼容行为,意味着如果你不额外指定头,服务器即便收到的是二进制内容,也会先按 URL 编码表单来理解请求体。

如果你希望服务器把数据当作**任意二进制(arbitrary binary data)**处理,文档给出的做法是显式覆盖该请求头:

curl --data-binary @blob.bin \ -H "Content-Type: application/octet-stream" \ https://upload.example.com/raw

实际项目中也常出现Content-Type: application/jsonapplication/pdfapplication/x-protobuf等覆盖写法,原理一致:-H中显式声明的 Content-Type 会覆盖选项内置的默认值。

多次使用的拼接语义(Multi: append)

选项元数据中的Multi: append意味着--data-binary可以重复出现,并且数据会按顺序累积。拼接规则继承自--data(docs/cmdline-opts/data.md 有完整描述):

If any of these options is used more than once on the same command line, the data pieces specified are merged with a separating &-symbol. Thus, using-d name=daniel -d skill=lousywould generate a post chunk that looks likename=daniel&skill=lousy.

翻译成--data-binary的等价行为:

# 最终请求体等价于 name=daniel&skill=lousy curl --data-binary "name=daniel" --data-binary "skill=lousy" $URL

这个&拼接对表单拼接很友好,但对二进制文件分块投递不友好:如果一段二进制数据里恰好含有&字节,拼接语义仍会原样保留它(--data-binary不会改写你的字节),只是在多次指定时,curl 会在两段数据之间主动插入一个&。因此,需要投递单个完整二进制文件的场景,请只使用一次--data-binary @file,不要拆成多段。

源码级原理:从命令行参数到请求体的调用链

步骤一:参数表注册

在命令行解析器 src/tool_getparam.c 中,--data-binary被注册为无短选项、参数类型为字符串的选项,并映射到内部枚举C_DATA_BINARY

{"data-binary", ARG_STRG, ' ', C_DATA_BINARY},

步骤二:统一分发到 set_data()

在 src/tool_getparam.c 处,--data--data-ascii--data-binary--data-urlencode--json--data-raw全部汇入同一个处理函数set_data(),这正是各选项行为相近、仅在细节上分野的原因。

步骤三:@前缀与文件读取分支

核心逻辑位于 src/tool_getparam.c 的set_data()

else if('@' == *nextarg && (cmd != C_DATA_RAW)) { /* the data begins with a '@' letter, it means that a filename or - (stdin) follows */ nextarg++; /* pass the @ */ ... if(cmd == C_DATA_BINARY) /* forced>if(curlx_dyn_len(&config->postdata)) { if(!err && (cmd != C_JSON) && curlx_dyn_addn(&config->postdata, "&", 1)) err = PARAM_NO_MEM; } ... config->postfields = curlx_dyn_ptr(&config->postdata);

这段代码从实现层面印证了"多次使用以&拼接"的文档语义,也解释了为什么--json不参与&拼接(JSON 载荷不适用表单分隔符)。累积完成的config->postfields指针随后会被传给 libcurl 的传输层选项CURLOPT_POSTFIELDS/CURLOPT_COPYPOSTFIELDS,其接收逻辑位于库侧 lib/setopt.c,配合 lib/setopt.c 处的CURLOPT_POSTFIELDSIZE_LARGE一起,libcurl 才能真正按字节长度(而非strlen)发送含空字节的二进制请求体。

调用链小结

--data-binary @file → src/tool_getparam.c 选项表 (C_DATA_BINARY) → getparameter() 分发 (case C_DATA_BINARY) → set_data() ├─ '@' 判定 → rb 打开文件 / 对 stdin 置二进制模式 ├─ file2memory() → 完整保留换行/回车/空字节 └─ dynbuf postdata 累积(多次指定时插入 '&') → config->postfields → libcurl CURLOPT_POSTFIELDS / CURLOPT_POSTFIELDSIZE (lib/setopt.c) → HTTP POST 请求体

实用示例集合

把上面的规则串起来,下面这些命令都值得收藏:

1. 从文件原样提交文本/JSON(保留所有换行缩进):

curl --data-binary @payload.json \ -H "Content-Type: application/json" \ https://httpbin.org/post

2. 提交任意二进制并告知服务器为字节流:

curl --data-binary @model.bin \ -H "Content-Type: application/octet-stream" \ https://upload.example.com/files

3. 从标准输入管道读取:

cat screenshot.png | curl --data-binary @- \ -H "Content-Type: application/octet-stream" \ https://upload.example.com/images

4. 直接内联 POST 二进制安全的字符串:

curl --data-binary "line1 line2" https://example.com/echo

(注意:内联模式下换行由 shell 引号内的真实换行决定,curl 原样发送。)

注意事项与易错点

  1. 协议范围仅为 HTTP--data-binary的协议标记是 HTTP,而--data还支持 MQTT(数据以 PUBLISH 语义发送)。涉及 MQTT 的载荷请使用--data家族而非--data-binary
  2. 二进制文件请单次指定:多次使用会插入&分隔,可能污染二进制流。
  3. 空字节需要配合正确的 Content-Type 与接收方:默认application/x-www-form-urlencoded下服务器可能拒绝或误解析,请显式覆盖请求头。
  4. @冲突:如果待投递内容本身以@开头且不想触发文件读取,请改选--data-raw(它放弃@解释,也不保留"读文件路径");如果必须从文件读取,--data-binary是正确选择。
  5. 使用场景判断:需保留换行、回车的文本(如格式化 JSON、多行报文),以及含空字节的任意二进制(图片、压缩包、序列化数据),都是--data-binary的典型适用面;普通键值对表单则优先--data/--data-urlencode

延伸阅读

  • 官方选项说明:docs/cmdline-opts/data-binary.md
  • 同族选项:docs/cmdline-opts/data.md、docs/cmdline-opts/data-raw.md、docs/cmdline-opts/data-ascii.md、docs/cmdline-opts/data-urlencode.md
  • 命令行解析实现:src/tool_getparam.c
  • 内嵌帮助文本生成:src/tool_listhelp.c
  • libcurl 侧请求体选项处理:lib/setopt.c

【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 19:38:16

Android第三方库选型与集成:从Gradle配置到依赖冲突排查全指南

简介&#xff1a;面向Android开发者的第三方库合集&#xff0c;系统梳理了Butter Knife、Gson、Retrofit、OkHttp、Glide、Dagger 2、EventBus、RxJava、Room等十余个主流库的用途与使用要点&#xff0c;帮助开发者快速选型并减少基础功能重复开发&#xff0c;适合初中级Androi…

作者头像 李华
网站建设 2026/9/9 19:37:44

一张图看懂计算机网络协议:从分层模型到排查实战

很多朋友在学网络知识时&#xff0c;最头疼的不是某一个协议有多难&#xff0c;而是协议数量太多&#xff0c;不知道它们各自属于哪一层&#xff0c;也不知道报文格式长什么样&#xff0c;更不清楚出了问题该用什么命令去排查。本文整理了一张相对完整的“计算机网络协议地图”…

作者头像 李华
网站建设 2026/9/9 19:35:18

傅里叶变换为何用负频率?卷积定理背后的符号约定与工程实践

1. 从一道“绕人”的问题说起&#xff1a;负频率到底是什么前几天有个学生拿着《信号与系统》教材跑来问我&#xff1a;老师&#xff0c;傅里叶变换公式里X(ω) ∫ x(t) e^(-jωt) dt&#xff0c;为什么要用负频率去“测”信号&#xff1f;卷积定理说时域卷积等于频域相乘&…

作者头像 李华
网站建设 2026/9/9 19:31:54

opencode不是工具,而是开发环境混沌的诊断信号

1. “opencode”到底是什么&#xff1f;别被名字骗了&#xff0c;它不是开源代码平台&#xff0c;也不是某个大厂新发布的AI编程工具 最近在技术社区和开发者群里&#xff0c;“opencode”这个词出现频率陡增&#xff0c;但翻遍GitHub、npm官网、主流技术媒体甚至招聘平台&…

作者头像 李华