通过PHP和cURL跨主机传输文件遇问题求助
PHP cURL 传输Google Drive文件问题解答
1. 生成空文件的原因及解决方法
空文件的核心原因是Google Drive的uc下载链接需要自动跟随重定向才能获取实际文件内容,默认curl配置不支持这一点,同时缺少错误处理导致请求失败时仍创建空文件。具体分析:
- Google Drive的下载链接会先跳转至实际文件存储地址,默认curl不会自动跟进重定向,因此返回空响应。
- 部分环境下curl无法验证Google的SSL证书,导致请求直接终止。
- 代码未检查curl执行结果,即使请求失败也会生成空文件。
修复后的代码:
<?php $source = 'https://drive.google.com/uc?id=xxxxxxxxxxxxxxxxx&export=download'; $filename = 'index.html'; // 打开文件句柄,检查写入权限 $fh = fopen($filename, 'w'); if (!$fh) { die('无法打开目标文件,请检查写入权限'); } $ch = curl_init($source); // 开启自动跟随重定向 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 临时关闭SSL验证(生产环境建议配置正确的CA证书路径) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 请求失败时直接返回false curl_setopt($ch, CURLOPT_FAILONERROR, true); // 设置文件写入句柄 curl_setopt($ch, CURLOPT_FILE, $fh); // 执行请求并检查结果 $response = curl_exec($ch); if (!$response) { echo '下载失败: ' . curl_error($ch); fclose($fh); // 删除生成的空文件 unlink($filename); exit; } // 清理资源 curl_close($ch); fclose($fh); echo '文件下载完成'; ?>
补充:如果是大文件,Google Drive可能会返回确认下载的页面,此时需要先请求链接提取Cookie和真实下载地址,再发起二次请求。
2. 修改目标文件名为index.html的方法
原代码中basename($source)会将URL的查询参数部分当作文件名,解决方式有两种:
方式一:手动指定文件名(推荐,适用于已知文件名的场景)
直接将basename($source)替换为'index.html',就像上面代码中定义的$filename = 'index.html',打开文件句柄时直接使用这个变量即可。
方式二:自动从响应头解析文件名(适用于未知文件名的场景)
通过curl获取响应头中的Content-Disposition字段,解析出原始文件名:
// 在curl_exec执行成功后添加 $contentDisposition = curl_getinfo($ch, CURLINFO_CONTENT_DISPOSITION); if ($contentDisposition && preg_match('/filename="?([^"]+)"?/', $contentDisposition, $matches)) { $originalFilename = $matches[1]; // 如果之前用临时文件名下载,可重命名为原始文件名 rename($filename, $originalFilename); }
内容的提问来源于stack exchange,提问作者amirihedar54
相关产品推荐
相关产品推荐

