php实现下载文件的方式,直接通过设置header在浏览器下载资源,通过fopen方式是可以的,但是有时候遇到https类型的不一定成功(亲测某些不行),然后我的解决方案就是用curl获取下来后再用fopen读取方式下载。代码如下:
class Download
{
//保存到本地
public static function remote2local($url, $localPath)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//开发环境取消ssl认证
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$res = curl_exec($ch);
if (curl_errno($ch)) {
echo "下载失败: " . PHP_EOL;
print_r(curl_error($ch));
exit('');
}
curl_close($ch);
//保存到本地
$file = fopen($localPath, 'w');
fwrite($file, $res);
fclose($file);
return $localPath;
}
/**
* 下载文件
* @param $url string 文件地址,支持远程url
* @param $filename string 下载的文件名
* @param $callback callable 回调函数
* @param $tmPath string 远程文件临时保存路径
* @param $delRemoteTmp bool 是否删除远程文件下载本地的文件
* @return void
*/
public static function download_file($url, $filename = '', $callback = null, $tmPath = null, $delRemoteTmp = false)
{
$filename = $filename ?? md5(time() . rand(1, 999999));
$path = parse_url($url, PHP_URL_PATH);
$extension = pathinfo($path, PATHINFO_EXTENSION);
$fileName = $filename . '.' . $extension;
if (stripos($url, 'http') === 0) {
//保存的临时路径
$tmPath = $tmPath ?? RUNTIME_PATH . '/data/download/';
if (!is_dir($tmPath)) mkdir($tmPath, 0777, true);
$localPath = self::remote2local($url, $tmPath . $fileName);
$isRemote = true;
} else {
$localPath = $url;
}
// 设置HTTP响应标头
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
$openFile = @fopen($localPath, 'rb');
if ($openFile) {
// 逐块输出文件内容到浏览器
while (!feof($openFile)) {
echo fread($openFile, 8192);
ob_flush();
flush();
}
$res = true;
fclose($openFile);
if (!empty($isRemote) && file_exists($localPath) && $delRemoteTmp) {
unset($localPath);
}
} else {
$res = false;
}
if (is_callable($callback)) {
call_user_func($callback, $res);
}
}
}支持远程文件和本地文件下载,调用实例:
Download::download_file($url,'文件abc',function ($res){
if ($res){
//统计下载量
}
});