我用的是 php ,问了一圈 AI ,告诉我使用 ZipStream ,但是我试了同样需要等待压缩的时候非常久,而不是像群晖 NAS 那样,立即开始下载,且浏览器不显示最终文件大小。 请问 v 友这是如何做到的
public function downloadFolderNew()
{
$path = $this->request->param("path", "");
if (!empty($path)) {
// 将路径转换为项目的公共路径
$path = str_replace("D:\\phpproject\\test\\public\\", public_path(), $path);
}
if (!is_dir($path)) {
$this->error("路径不存在");
}
$fileName = $this->request->param("file_name", "") ?: uniqid();
$zipFileName = $fileName . ".zip";
// 设置响应头
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zipFileName . '"');
header('X-Accel-Buffering: no'); // 关闭 Nginx 的输出缓冲
// 禁用输出缓冲区
if (ob_get_level()) {
ob_end_clean();
}
// 立即输出部分内容,浏览器开始下载
echo "\xEF\xBB\xBF"; // 避免 PHP 输出缓冲,立即开始下载
flush();
// 创建一个 ZIP 流
$zip = new ZipStream\ZipStream(null, [
'outputStream' => 'php://output' // 将输出直接定向到浏览器
]);
// 递归添加文件夹内容到 ZIP
$this->addFolderToZip($zip, $path, '');
// 结束 ZIP 流
$zip->finish();
exit();
}
private function addFolderToZip($zip, $folder, $zipPath)
{
// 创建迭代器,遍历文件夹中的文件
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($folder, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($folder) + 1); // 获取文件相对路径
if (!$file->isDir()) {
// 确保文件路径和内容正确添加到 ZIP 中
$zip->addFileFromPath($zipPath . $relativePath, $filePath);
}
// 刷新输出缓冲,逐步发送数据到浏览器
flush();
}
}
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.