一、写在开始
在上一篇博客中写了一个先压缩后分片下载的demo,但是存在一定的缺点,本篇介绍的是先分片然后放入压缩包最后再分片下载
二、具体代码
public function downloads()
{
$id = input();
$row = db('files')->where('id', $id['ids'])->find();
$datas = db('files')->where('uid', $row['uid'])->select();
$arr = [];
foreach ($datas as $key => $value) {
array_push($arr, $value['path']);
}
// 创建一个目录
$path = "./uploads/zip/" . date('Y-m-d');
if (!file_exists($path)) {
mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
}
// 创建一个压缩包
$zip = new \ZipArchive();
$zip_name = $path . '/' . date('H-i-s') . '.zip'; //压缩包路径
if ($zip->open($zip_name, \ZipArchive::CREATE) !== true) {
exit("压缩包文件创建失败!");
}
$chunk_size = 1024 * 1024; // 分片大小,这里设置为1MB
foreach ($arr as $file) {
$path_url = '.' . $file; //获取到的文件路径是从/uploads开始的
$handle = fopen($path_url, 'rb'); //打开该文件
if ($handle === false) {
exit('打开文件失败');
}
// fseek($handle , 0);
// 分片读取文件
while (!feof($handle)) {
$test = fread($handle, $chunk_size);
if ($test === false) {
exit('读取失败');
}
$zip->addFile($path_url, basename($path_url)); //向压缩包中添加文件
// flush();
// ob_flush();
}
fclose($handle); //关闭文件
}
$zip->close(); //关闭压缩包
// var_dump($zip_name);exit;
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . 'ya.zip"');
header('Accept-Ranges: bytes');
header('Content-Length:'. filesize($zip_name));
// readfile($zip_name);
$length = filesize($zip_name);
try {
// 打开文件,并获取文件大小
$fp = fopen($zip_name, 'rb');
if ($fp === false) exit("文件打开失败");
// 直接输出文件内容到浏览器
while (!feof($fp)) {
echo fread($fp, 8192);
}
} finally {
// 关闭文件
if ($fp !== false) fclose($fp);
// 删除临时目录和文件
// array_map('unlink', glob($temp_dir . '/*'));
// rmdir($temp_dir);
exit;
}
}