cURL远程文件操作必须设CURLOPT_RETURNTRANSFER为true,否则curl_exec()直接输出而非返回;二进制文件需加CURLOPT_BINARYTRANSFER;批量请求应使用curl_multi_init并发;大文件须用CURLOPT_FILE流式写入;禁用SSL验证不安全,应更新CA证书包;每次请求后须检查curl_errno()和curl_error()。

PHP 用 cURL 打开远程文件时,curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) 必须设为 true
不设这个选项,curl_exec() 默认直接输出响应体(比如图片、JSON、HTML),而不是返回字符串。你拿到的是 null 或空内容,后续处理全崩。
- 常见错误现象:
file_get_contents('https://...')能读,但自己写 cURL 却返回空 —— 很可能漏了这行 - 如果远程文件是二进制(如 PDF、PNG),还要加
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true),否则 Windows 下可能被截断或乱码 - 别用
echo curl_exec($ch)调试;先确保returntransfer开启,再用var_dump()看返回值长度和类型
批量请求远程文件时,curl_multi_init() 比循环单个 cURL 快 3–10 倍
串行调用 10 个 curl_exec() 是阻塞的:等第一个完成才发第二个。并发用 curl_multi 可让所有请求同时发出,总耗时接近最慢那个连接的响应时间。
- 必须手动管理句柄:
curl_multi_add_handle()→curl_multi_exec()循环等待 →curl_multi_getcontent()取结果 →curl_multi_remove_handle() - 别忘了设置超时:
curl_setopt($ch, CURLOPT_TIMEOUT, 10),否则某个挂起的请求会拖垮整个批处理 - 内存敏感场景下,一次并发数建议控制在 5–20 之间;太多句柄会触发系统限制(如 Linux 的
ulimit -n)
$mh = curl_multi_init();
$chs = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_multi_add_handle($mh, $ch);
$chs[$i] = $ch;
}
$active = null;
do {
curl_multi_exec($mh, $active);
} while ($active);
foreach ($chs as $i => $ch) {
$content = curl_multi_getcontent($ch);
// 处理 $content...
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
远程文件太大时,用 CURLOPT_FILE 流式写入磁盘,避免内存溢出
用 curl_exec() 把几百 MB 的 ZIP 全读进 PHP 字符串里,极易触发 Fatal error: Allowed memory size exhausted。正确做法是绑定一个文件句柄,边下载边写。
- 打开目标文件用
fopen($path, 'w'),然后传给curl_setopt($ch, CURLOPT_FILE, $fp) - 记得最后
fclose($fp);否则文件可能不完整(缓冲未刷出) - 如果需校验下载完整性(如比对
Content-Length或 MD5),得在CURLOPT_HEADERFUNCTION里捕获响应头,或下载后用filesize()核对
遇到 SSL certificate problem: unable to get local issuer certificate 不要简单关验证
很多人加 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false) 图省事,但这等于放弃 HTTPS 安全性,中间人攻击风险拉满。真正该做的是:
立即学习“PHP免费学习笔记(深入)”;
- 确认服务器是否用了 Let’s Encrypt 或其他主流 CA 签发的证书(大部分现代证书链没问题)
- 更新 PHP 的 CA 证书包:下载 cacert.pem,然后在
php.ini中设curl.cainfo="/path/to/cacert.pem" - 若用容器或旧系统(如 CentOS 6),可能需要手动更新系统级 CA 包:
update-ca-trust或apt install ca-certificates
实际批量下载逻辑里,最常被跳过的不是并发控制,而是每个请求后的错误检查:curl_errno($ch) 和 curl_error($ch) 必须每轮都查——网络抖动、DNS 失败、HTTP 4xx/5xx 都不会抛异常,只会静默返回空或错误内容。
