上传前验证文件扩展名和大小

Validate file's extension & size before uploading

我尝试制作一个文件上传器,它应该能够上传哑剧,即:.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);
        }
    }
}

blade

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

尽管上面的验证规则让我们假设如果我尝试上传 .zip.rar 文件,它们在 1GB 左右。文件首先上传,这需要相当多的时间,然后在验证后抛出错误。

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

使用这样的东西:

if(isset($_FILES['uploaded_file'])) {
    $errors     = array();
    $maxsize    = 2097152;
    $acceptable = array(
        'application/pdf',
        'image/jpeg',
        'image/jpg',
        'image/gif',
        'image/png'
    );

    if(($_FILES['uploaded_file']['size'] >= $maxsize) || ($_FILES["uploaded_file"]["size"] == 0)) {
        $errors[] = 'File too large. File must be less than 2 megabytes.';
    }

    if((!in_array($_FILES['uploaded_file']['type'], $acceptable)) && (!empty($_FILES["uploaded_file"]["type"]))) {
        $errors[] = 'Invalid file type. Only PDF, JPG, GIF and PNG types are accepted.';
    }

    if(count($errors) === 0) {
        move_uploaded_file($_FILES['uploaded_file']['tmpname'], '/store/to/location.file');
    } else {
        foreach($errors as $error) {
            echo '<script>alert("'.$error.'");</script>';
        }

        die(); //Ensure no more processing is done
    }
}

使用此 html 代码甚至不允许上传文件:

<input type="file"
       id="avatar" name="avatar"
       accept="image/png, image/jpeg">

参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file

为什么不用Request,在controller中调用Request

'files.*' => 'mimes:jpeg,jpg,png,pdf|max:1024',

不要使用逗号使用 OR 运算符来使用文件类型

PS:1024 KB,即 1MB

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

所以即使您尝试上传 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;
}

必须在服务器(后端)上进行验证

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