这一集我们要是实现的功能是,在用户注册模块,添加一个上传头像的功能。
通过php artisan route:list
看一下注册功能路由提交的地址,是在RegisterController@register
之中。但是打开RegisterController
后,发现根本没有resigter
方法。不用说了,这个register
方法一定又是放在了trait
之中了。
我们这里为了调试方便,自己在RegisterController
中,新建一个register
方法,这样laravel
自带的注册功能就不会生效了。
use Illuminate\Http\Request;
public function register(Request $request)
{
return $request->all();
}
上传头像的表单,我也已经准备好了,大家直接复制过来就好了。
<form method="post" class="am-form" action="{{ route('register') }}" enctype="multipart/form-data">
<!-- ... -->
<div class="am-form-group am-form-file">
<label class="am-form-label" for="avatar">头像: </label>
<br>
<button type="button" class="am-btn am-btn-success am-btn-sm">
<i class="am-icon-cloud-upload" id="loading"></i> 上传新的缩略图
</button>
<input type="file" id="photo_upload" name="file">
<input type="hidden" name="avatar" value="{{old('avatar')}}">
<hr data-am-widget="divider" class="am-divider am-divider-dashed am-no-layout">
<div>
<img src="{{ old('avatar', 'https://images.itfun.tv/school/images/common/user_noimg.png') }}" id="photo_show" style="max-height: 200px;">
</div>
</div>
<!-- ... -->
</form>
Tips:
需要注意的是,上传一定要在form
标签中加上enctype="multipart/form-data"
。只有这样,php
才能就收到上传的数据。
上传的input
这里的name
是file
,那么在php
那边也应该要使用file
这个名字来接受了。
public function register(Request $request)
{
//return $request->file;
$path = $request->file->store('public/images');
return $path;
}
那这里就,可以看到一个路径地址了,这就是我们刚才上传的文件了,只不过他还在一个临时目录之中。
其实在laravel
实现上传功能,非常的简单,只需要这一行代码就可以了。这里 store 的意思就是将临时目录中的文件,保存到我们指定的路径,也就是这里定义的public/images
。
打开文件夹,找到storage/app/public/images
路径中,这里就可以找到我们刚才上传的文件了。文件名是laravel
自动生成的一个唯一的名字,所以你不需要担心上传文件名字重复的问题。
但是有点问题,storage
这个路径通过浏览器是访问不到的。因为 laravel 的根目录
在public
目录中。所以,你还要使用这么一条命令,来建立一个storage
到public
的链接。
php artisan storage:link
这样上传功能其实已经实现了,并且通过浏览器地址栏也可以访问到了。
http://localhost:8000/storage/images/?.jpeg
实际上这样做并不完善,文件上传的一些基本的验证功能都没有做。那么我们就来继续增加一些代码吧。
//...
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class RegisterController extends Controller
{
//...
public function register(Request $request)
{
if (!$request->hasFile('file')) {
return response()->json(['message' => '没有上传文件'], 422);
}
if (!$request->file->isValid()) {
return response()->json(['message' => '文件上传过程中出错了'], 422);
}
//上传格式验证
$allow = ['image/jpeg', 'image/png', 'image/gif'];
$type = $request->file->getMimeType();
//return $type;
if (!in_array($type, $allow)) {
return response()->json(['message' => '文件类型错误,只能上传图片'], 422);
}
//文件大小验证
$max_size = 1024 * 1024 * 2;
$size = $request->file->getClientSize();
//return $size;
if ($size > $max_size) {
return response()->json(['message' => '文件大小不能超过2M'], 422);
}
$path = $request->file->store('public/images');
$url = Storage::url($path);
return $url;
}
}
如果一直提示没有上传文件
,或者直接报错,那可能是你上传的文件 > 2M。
你需要修改下php.ini
中,我这里是以mac os
上homebrew
安装的php 7.1
为例,vim /usr/local/etc/php/7.1/php.ini
。不同的环境,php.ini
的路径也不一样。
post_max_size = 20
upload_max_filesize = 20M
修改完php.ini
后,一定要重启服务。如果不是用命令行,而是apache
来运行的,那就必须重启apache
才会生效。
在 laravel 中上传文件,就是这么一个流程。但是这种做法的体验并不是特别好。
点击按钮后,页面不能马上就显示出用户的头像来,必须表单提交后上传的代码才会生效。
下一集我们会学习使用ajax
来完善上传功能。
已添加到喜欢了