Laravel 中创建 Zip 压缩文件并提供下载

图片

如果您需要您的用户支持多文件下载的话,最好的办法是创建一个压缩包并提供下载。看下在 Laravel 中的实现。

事实上,这不是关于 Laravel 的,而是和 PHP 的关联更多,我们准备使用从 PHP 5.2 以来就存在的 ZipArchive 类 ,如果要使用,需要确保php.ini 中的 ext-zip 扩展开启。

任务 1: 存储用户的发票文件到 storage/invoices/aaa001.pdf

下面是代码展示:

$zip_file = 'invoices.zip'; // 要下载的压缩包的名称

// 初始化 PHP 类
$zip = new \ZipArchive();
$zip->open($zip_file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

$invoice_file = 'invoices/aaa001.pdf';

// 添加文件:第二个参数是待压缩文件在压缩包中的路径
// 所以,它将在 ZIP 中创建另一个名为 "storage/" 的路径,并把文件放入目录。
$zip->addFile(storage_path($invoice_file), $invoice_file);
$zip->close();

// 我们将会在文件下载后立刻把文件返回原样
return response()->download($zip_file);

例子很简单,对吗?


任务 2: 压缩 全部 文件到 storage/invoices 目录中

Laravel 方面不需要有任何改变,我们只需要添加一些简单的 PHP 代码来迭代这些文件。

$zip_file = 'invoices.zip';
$zip = new \ZipArchive();
$zip->open($zip_file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

$path = storage_path('invoices');
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
foreach ($files as $name => $file)
{
    // 我们要跳过所有子目录
    if (!$file->isDir()) {
        $filePath     = $file->getRealPath();

        // 用 substr/strlen 获取文件扩展名
        $relativePath = 'invoices/' . substr($filePath, strlen($path) + 1);

        $zip->addFile($filePath, $relativePath);
    }
}
$zip->close();
return response()->download($zip_file);

到这里基本就算完成了。你看,你不需要任何 Laravel 的扩展包来实现这个压缩方式。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://laraveldaily.com/how-to-create-z...

译文地址:https://learnku.com/laravel/t/26087

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 7

写法没有问题,但在线上运营会出现问题,比如磁盘占满等,还是推荐用nginx的mod_zip来打包下载

2年前 评论
xiatian

response()->streamDownload() 了解一下。

2年前 评论

@xiatian 是多个文件打包下载不是流下载

2年前 评论
TigerLin
    public function zip()
    {
        $zip_file = 'invoices.zip'; // 要下载的压缩包的名称
        // 初始化 PHP 类
        $zip = new \ZipArchive();
        $zip->open($zip_file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
        $invoice_file = 'invoices/1.jpg';
       // 添加文件:第二个参数是待压缩文件在压缩包中的路径
       // 所以,它将在 ZIP 中创建另一个名为 "storage/" 的路径,并把文件放入目录。
        $zip->addFile(storage_path($invoice_file), $invoice_file);
        $zip->close();
       // 我们将会在文件下载后立刻把文件返回原样
        return response()->download($zip_file);
    }

写法基本一致,我在storage/app/public 下创建了 invoices目录,目录下有1.jpg图片,运行报错

ZipArchive::close(): Can't remove file: No such file or directory
1年前 评论
GuoLiang 1年前
lesstrap 11个月前
mengdodo 9个月前

请问 压缩文件 打包下载 的问题解决了吗?我这边是要实现图片的批量下载功能,但是这些图片是放在storage/app/protected文件夹内的,目的是限制URL访问,只能通过下载来获取。

11个月前 评论

如果文件存在锁占用的情况就会导致所有的文件添加压缩包失败
is_readable is_writeable 检测时可以读的
file_get_contents 也是可读的
这样的情况下 @zip->close 总是返回false 或报错 提示 没有这样的文件或目录
请问要怎么检测文件占用呢

6个月前 评论

找不到下载文件, 不知道怎么回事儿, 有同款的吗?

6个月前 评论
Cosmos 3周前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!