Laravel 5.5 图片上传与 Intervention Image 实现图片裁剪

发布时间:2018-05-06 编辑:小张个人博客 查看次数:7724

Laravel 上传图片

这里我们以用户上传头像案例来讲解,如何 Laravel 5.5 上传图片和 使用 Intervention Image 实现图片裁剪功能。

Laravel 上传图片


模型文件修改

首先我们需在 User 模型里将 avatar 字段加入到允许修改的白名单 $fillable 中:

模型文件修改

接下来我们在 资料编辑页面 的『个人简介』编辑框下面,增加头像上传的选项

resources/views/users/edit.blade.php

<div class="form-group">
    <label for="" class="avatar-label">用户头像</label>
    <input type="file" name="avatar">

    @if($user->avatar)
	<br>
	<img class="thumbnail img-responsive" src="{{ $user->avatar }}" width="200" />
    @endif
</div>

在 Laravel 中,我们可直接通过 请求对象(Request) 来获取用户上传的文件,如以下两种方法:

// 第一种方法
$file = $request->file('avatar');

// 第二种方法,可读性更高
$file = $request->avatar;

接下来我们将在 UsersController update() 方法中,利用 Laravel 的 dd() 调试方法,来查看文件上传的情况:app/Http/Controllers/UsersController.php      

   // 更新用户数据
    public function update(UserRequest $request,ImageUpload $upload, User $user)
    {
       dd($request->avatar);
       
        $user -> update($request ->all());
        return redirect()->route('users.show', $user->id)->with('success', '个人资料更新成功!');
    }

在图片或者文件上传时,为表单添加此句声明是必须的

  enctype="multipart/form-data"

multipart/form-data 声明

Laravel 的『用户上传文件对象』底层使用了 Symfony 框架的 UploadedFile 对象进行渲染,为我们提供了便捷的文件读取和管理接口,我们将在后面使用这些方法。

现在我们已经能得到用户上传的图片数据了,接下来是对图片进行存储。

存储用户上传图片

本项目中,我们不止上传头像需要用到『图片上传功能』,在后面发布帖子功能中,我们也将会允许用户上传图片,所以此处我们需要预先设计一下图片上传相关的逻辑,我们可以将『图片上传』核心操作做成一个工具类:app/Tool/ImageUpload.php

<?php

namespace App\Tool;

use Image;

class ImageUpload {

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

    public function save($file, $folder, $file_prefix,$max_width = false)
    {
        // 构建存储的文件夹规则,值如:uploads/images/avatars/201804/12/
        // 文件夹切割能让查找效率更高。
        $folder_name = "uploads/images/$folder/" . date("Ym/d", time());

        // 文件具体存储的物理路径,`public_path()` 获取的是 `public` 文件夹的物理路径。
        // 值如:/home/vagrant/Code/larabbs/public/uploads/images/avatars/201709/21/
        $upload_path = public_path() . '/' . $folder_name;

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

        // 拼接文件名,加前缀是为了增加辨析度,前缀可以是相关数据模型的 ID
        // 值如:1_1493521050_X7mXJ2n3p2.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"
            'path' =>  "/$folder_name/$filename"
        ];
    }
   
}

接下来我们需要在 UsersController 里调用:app/Http/Controllers/UsersController.php

// 更新用户数据
    public function update(UserRequest $request,ImageUpload $upload, User $user)
    {
        $data = $request -> all();
        // 处理上传图片保存并返回路径
        if($request -> avatar){
            $result = $upload ->save($request -> avatar,'avatar',$user ->id,362);
            if($result){
                $data['avatar'] = $result['path'];
            }
        }
	// 执行更新
        $user -> update($data);
        return redirect()->route('users.show', $user->id)->with('success', '个人资料更新成功!');
    }

修改个人空间,将头像的 src 属性修改为 {{ $user->avatar }}:resources/views/users/show.blade.php

 <div align="center">
    <img class="thumbnail img-responsive" src="{{ $user -> avatar }}" width="300px" height="300px">
</div>

用户上传图片

图片验证

当用户上传分辨率太小的图片时,会影响网站的美观,所以我们需要对图片的分辨率大小加以限制。得益于 Laravel 强大的表单验证功能,我们只需要在 UserRequest 中增加图片验证规则即可:app/Http/Requests/UserRequest.php

 public function rules()
    {
        return [
            // 验证规则
            'name' => 'required|between:3,25|regex:/^[A-Za-z0-9\-\_]+$/|unique:users,name,' . Auth::id(),
            'email' => 'required|email',
            'introduction' => 'max:80',
            'avatar' => 'mimes:jpeg,bmp,png,gif|dimensions:min_width=200,min_height=200',
        ];
    }
    public function messages()
    {
        return [
            'name.unique' => '用户名已被占用,请重新填写',
            'name.regex' => '用户名只支持中英文、数字、横杆和下划线。',
            'name.between' => '用户名必须介于 3 - 25 个字符之间。',
            'name.required' => '用户名不能为空。',
            'avatar.mimes' =>'头像必须是 jpeg, bmp, png, gif 格式的图片',
            'avatar.dimensions' => '图片的清晰度不够,宽和高需要 200px 以上',
        ];
    }

1、rules() 方法中新增了图片比例验证规则 dimensions ,仅允许上传宽和高都大于 200px 的图片;

2、messages() 方法中新增了头像出错时的提示信息。

裁剪图片

用户有时会上传分辨率较大的图片,图片太大会拖慢页面的加载速度,所以接下来我们将对此进行优化。

我们将使用有名的 Intervention/image 扩展包来处理图片裁切的逻辑,接下来我们需要先安装此扩展包;

Intervention/image 说明

Intervention/image扩展包是一个开源,PHP图像处理和操作,它提供了一个更简单的表达方式来创建、编辑、合成图像,支持目前最常见的两种图像处理库GD库和imagick。详细说明点击文档查看

系统要求

  • PHP >= 5.4

  • FileInfo 扩展


支持的图像库

  • GD Library (>=2.0)

  • Imagick PHP extension (>=6.5.7)

Composer 安装

composer require intervention/image

执行以下命令获取配置信息

php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5"

Intervention/image 配置文件

打开 config/image.php 文件可以看到只有一个驱动器的选项,支持的值有 GD 库 和 ImageMagic

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Image Driver
    |--------------------------------------------------------------------------
    |
    | Intervention Image supports "GD Library" and "Imagick" to process images
    | internally. You may choose one of them according to your PHP
    | configuration. By default PHP's "GD Library" implementation is used.
    |
    | Supported: "gd", "imagick"
    |
    */

    'driver' => 'gd'

];

开始裁剪

我们将裁切的逻辑写在 ImageUpload 中,请将以下代码替换:App\Tool\ImageUpload.php

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

        // 如果限制图片宽度,就进行裁剪
        if($max_width && $extension != 'gif'){
            // 此类中封装的函数,用于裁剪图片
            $this -> reduceSize($upload_path.'/'.$filename,$max_width);
        }
.
.
.
 // 用于裁剪图片
    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();

    }

以上的 save() 方法中,我们新增了 $max_width 参数,用来指定最大图片宽度,我们修改 UsersControllerupdate() 方法中的调用,修改为:

$result = $upload ->save($request -> avatar,'avatar',$user ->id,362);

1.jpg




出处:小张个人博客

网址:http://blog.023xs.cn/

您的支持是对博主最大的鼓励,感谢您的认真阅读。欢迎转载,但请保留该声明。

顶部

Copyright © 小张个人博客 All Rights Reserved 渝ICP备15006773号-1

联系方式:[email protected] | 本站文章仅供学习和参考

渝公网安备 50024102500267号