天天看点

图片上传、限制、裁剪功能

用户肯定都要有自己的头像,这就涉及到了图片的上传、裁剪等,其实很容易实现。

图片上传

直接使用file类型的input标签即可,我们可以通过accept属性来限制上传的文件类型,但是一般避免使用此属性,建议在服务器端验证文件上传。

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

这里有一点要注意,图片或文件上传时,必须为表单添加enctype声明,否则请求对象$request获取的就会是图片名称。

<form action="{{ route('users.update', $user->id) }}" method="POST" 
          accept-charset="UTF-8" 
          enctype="multipart/form-data">
           

可以在控制器中直接使用请求对象Request来获取上传的文件

$file = $request->avatar;    //avatar就是input标签的name属性值
           

但是,肯定不能获取到图片后直接存到数据库,那就太愚蠢了。一般情况下,图片上传功能是系统中经常使用的功能,所以可以将图片上传做成一个工具类,需要用到的时候就直接调用即可。

namespace App\Handlers;

use  Illuminate\Support\Str;

class ImageUploadHandler
{
    // 只允许以下后缀名的图片文件上传
    protected $allowed_ext = ["png", "jpg", "gif", 'jpeg'];

    public function save($file, $folder, $file_prefix)
    {
        //路径
        $folder_name = "uploads/images/$folder/" . date("Ym/d", time());
        $upload_path = public_path() . '/' . $folder_name;

        // 获取文件的后缀名,因图片从剪贴板里黏贴时后缀名为空,所以此处确保后缀一直存在
        $extension = strtolower($file->getClientOriginalExtension()) ?: 'png';

        // 文件名
        $filename = $file_prefix . '_' . time() . '_' . Str::random(10) . '.' . $extension;

        // 如果上传的不是图片将终止操作
        if ( ! in_array($extension, $this->allowed_ext)) {
            return false;
        }

        // 将图片移动到我们的目标存储路径中
        $file->move($upload_path, $filename);

        return [
            'path' => config('app.url') . "/$folder_name/$filename"
        ];
    }
}
           

接下来就可以在控制器中调用预先定义的图片上传工具类了。

use App\Handlers\ImageUploadHandler;

class UsersController extends Controller
{
    .
    .
    .

    public function update(UserRequest $request, ImageUploadHandler $uploader, User $user)
    {
        $data = $request->all();

        if ($request->avatar) {
            $result = $uploader->save($request->avatar, 'avatars', $user->id);
            if ($result) {
                $data['avatar'] = $result['path'];
            }
        }

        $user->update($data);
        return redirect()->route('users.show', $user->id)->with('success', '图片上传成功!');
    }
}
           

图片格式、分辨率限制

图片的格式、分辨率等可以很巧妙的通过表单验证功能进行限制。

public function rules()
    {
        return [
            'name' => 'required|between:3,25|regex:/^[A-Za-z0-9\-\_]+$/|unique:users,name,' . Auth::id(),
        ];
    }

    public function messages()
    {
        return [
            'avatar.mimes' =>'头像必须是 jpeg, bmp, png, gif 格式的图片',
            'avatar.dimensions' => '图片的清晰度不够,宽和高需要 208px 以上',
        ];
    }
           

图片的裁剪

composer备受推崇的主要原因就是可以方便的安装扩展包并处理好依赖关系,而此处图片的裁剪我们就通过composer安装一个叫Intervention/image的扩展包来处理图片的裁剪。

Composer安装扩展包

compser require intervention/image
           

必须在图片处理类里引用Image包,直接调用其中封装好的方法即可。

//裁剪方法
public function reduceSize($file_path, $max_width)
    {
        // 先实例化,传参是文件的磁盘物理路径
        $image = Image::make($file_path);

        // 进行大小调整的操作
        $image->resize($max_width, null, function ($constraint) {

            // 设定宽度是 $max_width,高度等比例缩放
            $constraint->aspectRatio();

            // 防止裁图时图片尺寸变大
            $constraint->upsize();
        });

        // 对图片修改后进行保存
        $image->save();
    }