在 Laravel 程序中上传文件时,请求验证可以很好验证上传的文件。你可以要求上传文件必须为 图片 , 也可以限制文件字节 大小 , 也可以根据 mime types 或者 文件扩展名 过滤文件。

如果我们希望用户上载 ZIP 文件,我们可以结合规则并像如下所示的内容使用:

return [
'file' => 'required|file|mimes:zip|size:3072'
];

  

但是与图片、文本或 pdf 文件不同,ZIP 是一个压缩文件,可以在其中保存多个不同的文件。 假设我们希望用户上传一个 ZIP 文件,但带有特定的必需文件和文件夹结构。 举一个真实的例子,如果您曾经使用过 Wordpress 并使用 ZIP 文件为其安装了主题,则 Wordpress 要求主题 ZIP 文件具有某些特定的文件,例如 style.css 或 post.php。 在 Laravel 中我们如何验证上传的 ZIP 文件以查看其是否包含所有必需文件?

PHP 的 libzip 扩展

这里会需要 php 的 libzip 扩展的支持,该扩展的启用以及具体用法请看文档 official documentation page.

如何操作 ZIP 文件

第一步,实例化 ZipArchive 类。

$zip = new \ZipArchive();

  

然后我们就可以通过 open() 方法来解压 ZIP 文档了。

$zip->open('/absolute/path/to/file.zip');

  

方法的官方文档 指出,如果成功打开 ZIP 文件,它将返回 “true”,否则返回整数错误代码。 我们可以像这样检查所有内容:

$zipStatus = $zip->open('/absolute/path/to/file.zip');
if (zipStatus !== true) {
threw new \Exception('Could not open ZIP file. Error code: ' . zipStatus);
} // 没问题,继续操作…

  

ZipArchive 类提供了多种方法来帮助我们读取 ZIP 文件的内容,其中一些方法是

  • count() - 返回 ZIP 文件中的文件数
  • getFromIndex() - 返回指定索引对应的文件
  • getNameIndex() - 返回指定索引的文件名
  • statIndex() - 返回指定索引对应文件的详细信息(文件名、大小等)

有了这些方法,如果我们想获得 ZIP 文件中的可用文件列表。 我们可以这样做:

$filesInside = [];
for ($i = 0; $i < $zip->count(); $i++) {
array_push($filesInside, $zip->getNameIndex($i));
} $zip->close();

  

由于一个 ZipArchive 实例可以同时处理一个 ZIP 文件,因此在处理完该文件后,我们需要使用 close()方法。 当您循环浏览多个 ZIP 文件或使用此类创建新的 ZIP 文件时,这一点尤其重要。

当你使用 ZipArchive 时有一点需要注意一下, “entity” 的概念,这里的 “entity” 并不单单是文件,他还包含所有文件夹以及子文件夹。这句话怎么理解呢?假设我们有个目录结构如下的文档:

- invoice.pdf
- profile_picture.jpg
- documents/
- homework.doc
- bills/
- january/
- payment.pdf

  

我们对当前文档执行 count() 操作可以得到当前文件数量,虽然我们只有 4 个文件,但 count() 方法返回的是 7 ,这是为什么呢?让我们打印一下 $filesInside 看它里面到底包含了什么吧。

$files = [
'invoice.pdf',
'profile_picture.jpg',
'documents/',
'documents/homework.doc',
'bills/',
'bills/january/',
'bills/january/payment.pdf'
];

  

可以看到,打印结果中并不仅仅有你的文件还有相应的文件夹。 这里你还可以通过 getNameIndex() 方法来获取完整的文件路径。

集成到 Laravel 程序中

现在,我们知道了如何使用 PHP 获取 ZIP 的文件列表,让我们将所有内容集成到 Laravel 中并验证上传的 ZIP 文件是否包含必需的文件。

假设我们需要用户上传一个 ZIP 文件,并且文件的 assets 目录中必须包含 thumbnail.jpg 和 style.css 文件。

- thumbnail.jpg
- assets/
- style.css

  

这是我们的控制器,该控制器处理带有名为 zip_file 的文件上传:

namespace App\Controllers;
use Illuminate\Http\Request; class UploadController
{
const REQUIRED_FILES = [
'thumbnail.jpg',
'assets/style.css',
]; public function upload(Request $request)
{
$zip = new \ZipArchive();
$file = $request->file('zip_file');
}
}

  

对我们从 Illuminate\Http\Request 中检索数据时,每个文件都返回一个 Illuminate\Http\UploadedFile 实例。我们可以在实例上使用 path() 方法返回上传的临时文件的绝对路径。

这是我们打开 ZIP 文件并使用 ZipArchive 类列出所有文件的方法。

public function upload(Request $request)
{
$zip = new \ZipArchive();
$file = $request->file('zip_file');
$zip->open($file->path()); $filesInside = [];
for ($i = 0; $i < $zip->count(); $i++) {
array_push($filesInside, $zip->getNameIndex($i));
}
}

  

现在我们可以使用诸如 array_intersect() 之类的方法将 REQUIRED_FILES 与 $filesInside 进行比对。如果交集元素数量不等于 REQUIRED_FILES 的元素数量,则意味着上传的 ZIP 文件中并不存在所有必需的文件,因此我们可以中止请求执行或返回验证错误。

$intersection = array_intersect(self::REQUIRED_FILES, $filesInside);

if (count($intersection) !== count(self::REQUIRED_FILES)) {
abort(422);
}

  

这是我们的控制器,一切就绪:

namespace App\Controllers;
use Illuminate\Http\Request; class UploadController
{
const REQUIRED_FILES = [
'thumbnail.jpg',
'assets/style.css',
]; public function upload(Request $request)
{
$zip = new \ZipArchive();
$file = $request->file('zip_file');
$zip->open($file->path()); $filesInside = [];
for ($i = 0; $i < $zip->count(); $i++) {
array_push($filesInside, $zip->getNameIndex($i));
} $intersection = array_intersect(self::REQUIRED_FILES, $filesInside); if (count($intersection) !== count(self:: REQUIRED_FILES)) {
abort(422);
} // ZIP contains all required files, continue
}
}

  

最佳实践

在 Laravel 应用程序中,最佳实践是将与验证相关的内容移出控制器。 常见选项有:

出于 ZIP 内容验证的需要,我创建了一个专用的 Laravel 软件包,该软件包几乎完成了本博客文章中所述的所有操作,并提供了更多选项和功能。 您可以在 GitHub 页面查看 orkhanahmadov/laravel-zip-validator 以获取更多信息以及如何使用它。

更多学习内容请访问:

腾讯T3-T4标准精品PHP架构师教程目录大全,只要你看完保证薪资上升一个台阶(持续更新)​

如何 Laravel 中验证 zip 压缩包里的文件?的更多相关文章

  1. Java中往zip压缩包追加文件

    有个需求,从某个接口下载的一个zip压缩包,往里面添加一个说明文件.搜索了一下,没有找到往zip直接添加文件的方法,最终解决方法是先解压.再压缩. 具体过程如下: 1.一个zip文件的压缩和解压工具类 ...

  2. jeecg项目将workbook 的Excel流添加到zip压缩包里导出

    1.直接献出代码 Map<String,List<ConfidentialInformation>> typeMap = new HashMap<>(); try ...

  3. laravel中如何防止直接访问.env文件

    .env文件含有数据库账号密码等敏感数据,在laravel5.2中,在本地访问127.0.0.1/laravel/.env可直接访问到.env. 为避免.env被直接访问,可使用重定向,方法如下: 在 ...

  4. 怎么往mac中finder个人收藏里添加文件夹

    1.打开Finder,点击左上角finder偏好设置 2.选择边栏 3.如果侧栏中没有的文件夹,直接长按文件夹直接拖入.

  5. laravel中的storePublicly对上传的文件设置上传途径

    public function imgeUpload(Request $request) { //生成的文件名是md5随机的文件名字 //$path=$request->file('wangEd ...

  6. zip压缩包密码破解

    有一种破解方法叫做Known plaintext attack.市面上的密码破解软件几乎都带有这个功能.操作方法就是找到加密压缩包中的任意一个文件,用同样的压缩软件同样的压缩方式压缩成一个不加密的包, ...

  7. 【CTF 攻略】CTF比赛中关于zip的总结

    [CTF 攻略]CTF比赛中关于zip的总结   分享到: --> 本文首发于安全客,建议到原地址阅读,地址:http://bobao.360.cn/ctf/detail/203.html 前言 ...

  8. laravel中的验证及利用uploadify上传图片

    $rules = [ 'password'=>'required|between:6,20|confirmed', ]; $message = [ 'password.required'=> ...

  9. laravel 中使用tinker 验证驱动加载是否成功

    在验证laravel 中   InvalidArgumentException Driver [WeiBo] not supported. public function weibo() { retu ...

随机推荐

  1. Python爬虫系列(五):分析HTML结构

    今晚,被烦死了.9点多才下班,就想回来看书学习,结果被唠叨唠叨个小时,我不断喊不要和我聊天了,还反复说.我只想安安静静看看书,学习学习,全世界都不要打扰我 接着上一个讨论,我们今晚要分析HTML结构了 ...

  2. C# 发布时出现:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误

    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provider: SQL ...

  3. bat批处理文件搞定所有系统问题

     bat批处理文件搞定所有系统问题  分类: WINDOWS   -----------bat批处理文件搞定所有系统问题---------   一.查漏补缺——给系统功能添把火  我们的操作系统虽然功 ...

  4. CSS3 制作正方体

    一.预备知识 变形属性 2D变形属性 transform:他是css3中的变形属性: 通过transform(变形) 来实现2d 或者3d 转换,其中2d 有,缩放 scale(x, y) ,移动 t ...

  5. 选择IT行业的自我心得,希望能帮助到各位!(二)

    在前面说道的一,希望大家能喜欢,这也只是自己的一种经历,每个人都有年轻的时候,谁的年级都有自以为是,谁的年轻都有风华正茂,谁的年轻都让自己的内涵给我们自己摔了一个狠狠的道理,人外有人天外有天.我记得当 ...

  6. three.js obj转js的详细步骤 convert_obj_three.py的用法

    three.js是最近非常流行的一个前端webgl库. js格式的模型文件是three.js中可以直接加载的文件.使用THREE.JSONLoader()直接加载,而不需要引用其它的loader插件. ...

  7. 微信群里一道六年级数学题,求阴影面积,那我只能用python代码了

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...

  8. E. Max Gcd

    单点时限: 2.0 sec 内存限制: 512 MB 一个数组a,现在你需要删除某一项使得它们的gcd最大,求出这个最大值. 输入格式 第一行输入一个正整数n,表示数组的大小,接下来一行n个数,第i个 ...

  9. codeforces Equalizing by Division (easy version)

    output standard output The only difference between easy and hard versions is the number of elements ...

  10. Redis开发运维的陷阱及避坑指南

    原文首发于博客园,作者:后青春期的Keats:地址:https://www.cnblogs.com/keatsCoder/ 转载请注明,谢谢! Linux 配置优化 我们在使用 Redis 过程中,可 ...