首页 > 解决方案 > 上传前验证文件的扩展名和大小

问题描述

我试图制作一个文件上传器,它应该能够上传 mimes,即:.jpg, .jpeg, .pdf, .bmp, .png, .doc & .docx。我还提出了一个请求规则,如下所示:

StoreFileRequest.php

public function rules()
{
    'files.*' => [
        'mimes:jpg,jpeg,pdf,bmp,png,doc,docx',
        'max:20000',
    ],
}

控制器

use App\Http\Requests\Backend\StoreFileRequest;

public function store(StoreFileRequest $request)
{
    if($request->hasFile('files'))
    {
        foreach ($files as $file) {
            //file Mime type
            $fileMimeType=$file->getClientMimeType();

            //change filename to laravel generated name using above extention
            $filename=$file->hashName();

            //upload file
            $path=$file->storeAs('public/user-existing-health-reports/'.auth()->user()->uuid,$filename);
        }
    }
}

{!! Form::file('files[]',
    array('class' => 'form-control btn btn-file ',
    'accept'=>'.jpg, .jpeg, .pdf, .bmp, .png, .doc, .docx',
    'multiple',
    'required',
    )) !!}

尽管有上面的验证规则,让我们假设如果我尝试上传一个.zip& 还有一个.rar1GB. 该文件首先被上传,这需要相当长的时间,然后在验证后引发错误。

我的问题:我需要在用户单击提交按钮时验证文件扩展名和大小,然后再上传文件以通过验证器进行验证。

标签: phplaravelvalidationfile-uploadlaravel-8

解决方案


一旦收到请求数据,验证规则和请求数据验证就会在服务器上发生。

所以很自然,即使您尝试上传 2GB 文件或 zip 文件,它也必须先到达服务器,然后才能根据验证规则进行验证。

您还必须在前端实现一些验证以防止此类问题。

例如,您可以检查在前端上传的文件的 mime 类型和大小(通过 javascript),并且只有当它在前端通过验证时才允许使用上传的文件向服务器发出请求。

但是,永远不要只依赖前端的验证。服务器级别的验证是必须的。

例如验证上传的文件大小不超过 20MB

function isValidSize(file) {
    const errors = [];

    const maxUploadSizeInBytes = 20 * 1024 * 1024;

    let valid = true;

    if (file.size > maxUploadSizeInBytes) {

        valid = false;

        let sizeInKb = maxUploadSizeInBytes / 1024;

        let sizeForHumans = sizeInKb < 1024
            ? `${sizeInKb} KB`
            : `${sizeInKb / 1024} MB`;

        this.errors.push(
            `The file exceeds the maximum allowed size of ${sizeForHumans}`
         );
    }

    return valid;
}

根据允许的 mime 类型验证上传文件的 mime 类型的功能

isValidType(file) {
    const errors = [];

    let acceptedMimes = "jpg,jpeg,png,webp"
        .trim()
        .split(",")
        .map(type => `image/${type}`);

    let valid = true;

    if (!acceptedMimes.includes(file.type)) {
        valid = false;

        let phrase = acceptedMimes.replace(/,/g, " or ");

        this.errors.push(
            `The file type is not allowed. Please upload ${phrase} file.`
        );
     }

     return valid;
}

服务器(后端)的验证是必须的

前端验证是为了更好的用户体验和节省一些不必要的网络请求

推荐阅读