分片上传前须流式读取文件并用std::vector缓冲,设512kb~4mb大小、binary模式打开,用read()和gcount()处理末片;分片id用文件路径+偏移生成,校验优先sha-256;libcurl需禁expect头、设octet-stream类型、用readfunction流式上传;断点续传依赖本地状态文件记录已传id及文件元信息。

分片上传前必须处理的文件读取问题
直接用 std::ifstream 一次性读整个大文件进内存会爆掉,尤其在嵌入式或低内存环境。必须流式读取 + 分块缓冲,且不能依赖 std::string 存原始二进制数据(有 \0 截断风险)。
实操建议:
- 用
std::vector<:byte></:byte>(C++20)或std::vector<char></char>作缓冲区,大小设为 512KB~4MB,兼顾 IO 效率和内存压力 - 打开文件时务必加
std::ios::binary标志,否则 Windows 下换行符会被悄悄转换 - 用
file.read(reinterpret_cast<char>(buf.data()), buf.size())</char>读取,再用file.gcount()拿真实字节数——这是最后一片常小于缓冲区的关键判断依据
如何生成每个分片的唯一标识和校验值
服务端靠分片 ID 和总片数做合并顺序控制,靠校验值防传输损坏。别用简单递增序号当分片 ID,重传时容易覆盖错片。
实操建议:
- 分片 ID 推荐用
file_path + "_" + std::to_string(offset)(offset 是该片起始字节偏移),天然幂等且可追溯 - 校验值优先用 SHA-256,但 C++ 标准库不内置,可用 OpenSSL 的
EVP_DigestInit,或轻量级方案:对当前分片 buffer 做std::accumulate异或(仅用于快速完整性初筛,不替代哈希) - 把分片元数据(ID、offset、size、checksum)打成 JSON 字符串随分片一起 POST,别存在 HTTP Header 里——Header 有长度限制且不易调试
HTTP 分片上传请求怎么发才稳定
用 libcurl 是最现实的选择,但默认行为会破坏二进制分片:它可能自动加 Expect: 100-continue,导致小分片卡住;也可能把 Content-Type 设成 text/plain,让服务端解析失败。
实操建议:
- 关掉 expect continue:
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers)配"Expect:"空头 -
Content-Type必须显式设为"application/octet-stream",哪怕只是占位 - 用
CURLOPT_READFUNCTION+CURLOPT_READDATA流式上传 buffer,避免把整片 load 进内存再传——这对 >100MB 的片很关键 - 超时至少设
CURLOPT_TIMEOUT_MS为 30000,公网上传波动大,5 秒超时基本等于必失败
客户端如何安全地恢复断点续传
用户关程序、网络闪断、服务端返回 503,都会中断上传。没断点逻辑的话,只能从头再来,体验极差。
实操建议:
- 每上传完一片,立刻写一个本地状态文件(如
upload_state.json),内容含已传分片 ID 列表、总片数、文件最后修改时间(用于检测源文件是否被替换) - 启动上传前先读这个状态文件,用
std::set存已传 ID,后续循环跳过这些 ID - 别用文件名当状态键——用户可能改名;用文件全路径 +
stat.st_mtime+stat.st_size三元组做状态文件名,能规避大部分误判
真正难的不是发请求,而是判断哪片该重传、哪片其实服务端已收到但响应丢了。这部分得和服务端协议对齐,比如约定 200 响应体里必须返回 {"received": true, "part_id": "xxx"},客户端只认这个才算成功。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











