请问如何实现大文件夹即时浏览器下载 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
saveai
V2EX    程序员

请问如何实现大文件夹即时浏览器下载

  • &nsp;
  •   saveai 2024-09-11 16:43:01 +08:00 2386 次点击
    这是一个创建于 402 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我用的是 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(); } } 
    12 条回复    2024-09-13 08:44:40 +08:00
    kele1997
        1
    kele1997  
       2024-09-11 17:23:25 +08:00
    https://go.dev/play/p/RPK_Xmq0RPK

    我用了 go 语言,是能够支持边压缩,边下载的
    dode
        2
    dode  
       2024-09-11 17:25:31 +08:00
    流式处理,把 zip 的输出流设置为浏览器的输入流
    ntedshen
        3
    ntedshen  
       2024-09-11 17:36:07 +08:00
    不看注释都知道是 nginx 用户。。。
    因为我写 php 的时候也没搞定那个疑似是缓存的缓存问题。。。。。。。。。。。。。。。。

    群晖没测过。。。
    mega 点击下载 zip 文件以后是前端分片下载单个文件然后前端自己打包的。。。
    我现在自己写 nas 也是造 mega 造的。。。
    okakuyang
        4
    okakuyang  
       2024-09-11 19:22:13 +08:00
    因为 zip 的文件格式特性,应该是可以是实现一边压缩一边传输的。由于压缩还在进行中,程序还没有计算出最后的文件大小,所以不会开始就告诉浏览器文件大小。
    zhuangzhuang1988
        5
    zhuangzhuang1988  
       2024-09-11 20:47:32 +08:00
    java 的话有个 netty
    中间插入个中间层就可以了
    https://netty.io/4.1/xref/io/netty/handler/codec/http/HttpContentEncoder.html#L194
    wxf666
        6
    wxf666  
       2024-09-11 23:16:30 +08:00
    @okakuyang #4 能不能遍历下文件,提前算好总大小,以《打包存储》形式压缩,传输过程中由 gzip 压缩呢?
    billccn
        7
    billccn  
       2024-09-12 02:56:01 +08:00
    你把 CompressionMethod 设置成 STORE (就是不压缩)试试?或者把 defaultDeflateLevel 调整一下。

    另外显示的大小是在 HTTP 头里的,你不提前算好所有文件+zip 开销,等 HTTP 头都发完了才开始遍历目录那肯定不会有大小的。
    leonshaw
        8
    leonshaw  
       2024-09-12 09:42:46 +08:00 via Android
    有没有办法续传呢
    sunchuo
        9
    sunchuo  
       2024-09-12 10:54:56 +08:00
    okakuyang
        10
    okakuyang  
       2024-09-12 11:01:19 +08:00
    @wxf666 额,不是很了解 gzip 的机制,但是估计和 zip 差不多是把单个文件进行压缩,zip 设置成打包不压缩,理论上会很快生成 zip 文件,然后传输给 gzip ,感觉不是很靠谱。
    siweipancc
        11
    siweipancc  
       2024-09-13 08:42:35 +08:00 via iPhone
    206 请求+队列+二进制合并
    siweipancc
        12
    siweipancc  
       2024-09-13 08:44:40 +08:00 via iPhone
    需要有自定义下载条,建议楼主参考下 asmr.one 的实现。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2495 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 10:47 PVG 18:47 LAX 03:47 JFK 06:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86