今天实现了图片裁剪上传的功能,写下这篇blog,预防以后忘记

图片外链托管在github,图片无法加载请自备梯子

(1)前端实现

(1.1)cropper插件介绍

1
2
我们可以使用 cropper插件实现裁切和缩略图功能
下载地址为:https://github.com/fengyuanchen/cropper

(1.2)cropper插件使用

(1.2.1)准备

1
2
解压下载下来的压缩包
并把dist目录下的:cropper.min.js和cropper.min.css文件复制到项目目录下

(1.2.2)引入类库

1
2
3
4
<!--使用绝对路径引入类库,因为cropper是基于jquery的,所以jquery也要引入-->
<script src="/js/jquery.min.js"></script>
<link rel="stylesheet" href="/css/cropper.min.css">
<script src="/js/cropper.min.js"></script>

(1.2.3)html结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<form action="{{ route('setface') }}" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="form-div">
<input type="file" name="face">
</div>
<!-- 预览图片区域 -->
<div class="img-container">
<img id="pre_image">
</div>
<!-- 三个缩略图预区域 -->
<div class="docs-preview clearfix">
<div class="img-preview preview-lg"></div>
<div class="img-preview preview-md"></div>
<div class="img-preview preview-sm"></div>
</div>
<!-- 保存裁切参数的四个框 -->
<input type="hidden" name="x">
<input type="hidden" name="y">
<input type="hidden" name="w">
<input type="hidden" name="h">

<div class="form-div">
<input type="submit" value="确认">
</div>
</form>

(1.2.4)样式文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!--在头部把样式文件导入,也可以自己修改样式控制裁剪框-->
<style>
.img-container {
width: 240px;
height: 240px;
float:left;
}
.img-container #pre_image {
width: 100%;
}
.img-preview {
float: left;
overflow: hidden;
margin-left: 20px;
}

.preview-lg {
width: 240px;
height: 240px;
}

.preview-md {
width: 80px;
height: 80px;
}

.preview-sm {
width: 35px;
height: 35px;
}
</style>

(1.2.5)js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<script>

var preImg = $("#pre_image");
// 获取裁切时的四个框
var x = $("input[name=x]");
var y = $("input[name=y]");
var w = $("input[name=w]");
var h = $("input[name=h]");
// 选择图片时预览图片 并 调用cropper插件
$("input[name=face]").change(function(){
// 先消毁,清除一下插件,否则连续调用插件时会失败
preImg.cropper("destroy");
// this.files[0]:获取当前图片并转成URL地址
var url = getObjectUrl( this.files[0] );
console.log( url )
// 设置url到预览图片上
preImg.attr('src', url);
// 调出插件
preImg.cropper({
aspectRatio: 1, // 裁切的框形状
preview:'.img-preview', // 显示预览的位置
viewMode:3, // 显示模式:图片不能无限缩小,但可以放大
// 裁切时把参数保存到表单中
crop: function(event) {
x.val( event.detail.x );
y.val( event.detail.y );
w.val( event.detail.width );
h.val( event.detail.height );
}
});
});
// 预览时需要使用下面这个函数转换一下
function getObjectUrl(file) {
var url = null;
if (window.createObjectURL != undefined) {
url = window.createObjectURL(file)
} else if (window.URL != undefined) {
url = window.URL.createObjectURL(file)
} else if (window.webkitURL != undefined) {
url = window.webkitURL.createObjectURL(file)
}
return url
}

</script>

(1.2.6)

前端实现效果预览预览


(2)后端保存图片到数据库

(2.1)创建迁移文件

1
2
<!--为用户表表添加三个字段,用来保存三张缩略图-->
php artisan make:migration add_faces_users --table=users

(2.1.1)编写迁移文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddFacesUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('bgface')->nullable()->comment('大脸');
$table->string('mdface')->nullable()->comment('中脸');
$table->string('smface')->nullable()->comment('小脸');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['bgface','mdface','smface']);
});
}
}

(2.1.2)执行迁移

1
php artisan migrate

(2.2)创建表单验证类

(2.2.1)创建验证类文件

1
php artisan make:request FaceRequest

(2.2.2)编写验证规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class FaceRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
<!--最大上传大小不能超过4m-->
'face' => 'required|image|max:4096',
'x' => 'required|numeric|min:0',
'y' => 'required|numeric|min:0',
'w' => 'required|numeric|min:200',
'h' => 'required|numeric|min:200',
];
}
}

(2.3)配置路由

1
2
3
<!--配置一个用来处理头像的路由-->
//修改头像
Route::post("/face",'FaceController@face')->name('setface');

(2.4)FaceController中添加处理头像的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!--使用composer安装图片处理类-->
composer require intervention/image
<!--修改 config/app.php ,注册类到 $providers 数组-->
Intervention\Image\ImageServiceProvider::class
<!--在 $alias 数组中定义类别名-->
'Image'=> Intervention\Image\Facades\Image::class
<!--引入相关类-->
use Image;
use App\Models\User;
use Storage;
use App\Http\Requests\FaceRequest;
<!--添加face方法-->
public function face(FaceRequest $req) {

if($req->has('face') && $req->face->isValid())
{
// 当前图片上传的位置
$oldimage = $req->face->path();
// 保存原图片
// 获取当前日期
$date = date('Ymd');
$oriImg = $req->face->store('face/'.$date);
// 打开要处理的图片
$img = Image::make($oldimage);
// 裁切图片
$img->crop((int)$req->w,(int)$req->h,(int)$req->x,(int)$req->y);
// 生成缩略图并保存
// 拼出这个缩略图的名字
$bgname = str_replace('face/'.$date.'/', 'face/'.$date.'/bg_', $oriImg);
$img->resize(240,240);
$img->save('./uploads/'.$bgname);
$mdname = str_replace('face/'.$date.'/', 'face/'.$date.'/md_', $oriImg);
$img->resize(80,80);
$img->save('./uploads/'.$mdname);
$smname = str_replace('face/'.$date.'/', 'face/'.$date.'/sm_', $oriImg);
$img->resize(35,35);
$img->save('./uploads/'.$smname);
// 先取出用户的信息
$user = User::find( session('id') );
// 删除原头像
Storage::delete( $user->face );
Storage::delete( $user->bgface );
Storage::delete( $user->mdface );
Storage::delete( $user->smface );
// 更新新脸
$user->face = $oriImg;
$user->bgface = $bgname;
$user->mdface = $mdname;
$user->smface = $smname;
$user->save();
// 修改SESSION中的图片
session([
'smface' => $smname,
'bgface' => $bgname,
]);
return redirect()->route('face');
}
}

(3)注意事项

  • 数据库字段要对应正确,不然保存数据库会失败
  • 因为新的头像要保存到session中,所以如果没效果要多清空缓存试试
  • 最重要的是一定要有耐心
  • 注意一下文件的上传大小
  • 有问题请给我发邮件