std::filesystem::create_directories仅创建目录,不检查可写性、磁盘空间或挂载点状态,故不能替代下载前完整路径准备;需后续用is_writable等验证,并确保临时文件与目标同分区以保障rename原子性。

为什么 std::filesystem::create_directories 不能代替下载前的路径准备
因为它的职责只是建目录,不检查父路径是否可写、磁盘是否满、挂载点是否只读。下载中途失败再重试时,如果目标目录权限突变或磁盘空间耗尽,create_directories 仍会成功返回,但后续 fopen 或 std::ofstream 会静默失败或抛异常。
实操建议:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 调用
std::filesystem::create_directories后,立刻用std::filesystem::is_writable检查目标目录(C++20);若不可用,降级尝试access(path.c_str(), W_OK)(POSIX)或GetFileAttributes(Windows) - 临时文件必须写入与最终路径同磁盘分区,否则原子性
rename会失败——重试时得先清理残留临时文件,否则下次rename报File exists - 不要在重试循环里反复调用
create_directories,它开销小但无意义;路径准备应只做一次,在重试逻辑外完成
如何让 libcurl 的重试真正“可控”,而不是无限卡死
默认 CURLOPT_CONNECTTIMEOUT_MS 和 CURLOPT_TIMEOUT_MS 控制的是单次请求生命周期,但网络抖动常表现为连接建立成功、传输卡在中间——此时 timeout 不触发,libcurl 会一直等下去。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须同时设置:
CURLOPT_LOW_SPEED_LIMIT(如1024)、CURLOPT_LOW_SPEED_TIME(如30),否则慢速网络下重试机制形同虚设 -
CURLOPT_FAILONERROR设为1L,避免 HTTP 4xx/5xx 被当成成功响应吞掉,导致错误码被忽略 - 重试间隔不能固定,要用指数退避:
sleep(1 ,最大不超过 30 秒;第 1 次失败后等 1 秒,第 2 次等 2 秒,第 3 次等 4 秒……否则并发多任务时容易集体撞上服务端限流
临时文件命名和清理为什么必须用 std::tmpnam_s(Windows)或 mkstemp(Linux)
手拼 "temp_" + std::to_string(getpid()) + ".bin" 看似简单,实际会导致竞态:同一进程多次下载、或不同进程用相同 PID(容器场景常见),临时文件名冲突,write 覆盖彼此,重试时读到脏数据。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- Linux 下用
mkstemp,模板字符串必须含六个X:char tmpl[] = "/tmp/download_XXXXXX";返回 fd 直接用于curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fd) - Windows 下用
std::tmpnam_s+_sopen_s,避免tmpnam的线程不安全;生成路径后立即_sopen_s(&fd, path, ...),防止路径生成后被其他进程占用 - 每次重试前,先
unlink(POSIX)或DeleteFile(Windows)旧临时文件;但注意:若上一次重试崩溃退出,临时文件可能残留,需在工具启动时扫描并清理*.part或*.tmp类型文件
重试时如何避免重复下载整个大文件
HTTP 断点续传不是默认开启的,libcurl 默认从头开始——对 500MB 文件重试 3 次,就是 1.5GB 流量白跑。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 下载前先 HEAD 请求,检查响应头是否含
Accept-Ranges: bytes;不含则放弃断点,直接全量重试 - 本地已有临时文件时,用
std::filesystem::file_size获取已下载字节数,设置CURLOPT_RESUME_FROM_LARGE并追加请求头:"Range: bytes=" + std::to_string(already_downloaded) + "-" - 务必校验服务器返回的
Content-Range头是否匹配预期起始位置,否则可能是服务端忽略 Range 导致从头发包——此时应清空临时文件,降级为全量下载


















