在Laravel项目中实现Ajax上传用户头像

JellyBool

JellyBool

在编写web程序的过程中,经常会遇到一个经典的文件上传场景:上传头像(图片)。基于对最好的用户体验的追求,写一下之前在项目中实现在Laravel项目中的Ajax上传头像。

1.配置路由

在Laravel的routes.php中设置路由:

Route::get('/avatar/upload','UsersController@avatar');
Route::post('/avatar/upload','UsersController@avatarUpload');

2.配置控制器

UsersController.php中增加对应的avataravatarUpload这两个方法,前者用来渲染视图,后者处理实际上传的图像文件。

 public function avatar()
    {

        return view('users.avatar');
    }

  public function avatarUpload()
    {
    //some codes to deal with upload avatar
    }

3.编写前端代码

这其实就是在对应的users/文件夹的avatar.blade.php视图文件中设置样式,以下的HTML的各个标签可以根据自己的情况设置classid:

<header class="profile-header">
 <img id="user-avatar" src="https://wt-prj.oss.aliyuncs.com/0d06af79c49d4e08abb1ab3f7ab6e860/772c684b-10a4-43cf-8eec-dda9e28a5a23.png">
<div id="validation-errors"></div>
 <div class="avatar-upload" id="avatar-upload">
 {!! Form::open( [ 'url' => ['/avatar/upload/api'], 'method' => 'POST', 'id' => 'upload', 'files' => true ] ) !!}
<a href="#" class="btn button-change-profile-picture">
<label for="upload-profile-picture">
<span id="upload-avatar">更换新头像</span>
 <input name="image" id="image" type="file" class="manual-file-chooser js-manual-file-chooser js-avatar-field">
</label>
</a>
{!! Form::close() !!}
 <div class="span5">
<div id="output" style="display:none">
</div>
</div>
<span id="filename"></span>
 </header>

在js中实现Ajax请求,这里的Ajax借助了Jquery的第三方插件http://malsup.com/jquery/form/

$(document).ready(function() {
            var options = {
                beforeSubmit:  showRequest,
                success:       showResponse,
                dataType: 'json'
            };
            $('#image').on('change', function(){
                $('#upload-avatar').html('正在上传...');
                $('#upload').ajaxForm(options).submit();
            });
        });
    function showRequest() {
        $("#validation-errors").hide().empty();
        $("#output").css('display','none');
        return true;
    }

    function showResponse(response)  {
        if(response.success == false)
        {
            var responseErrors = response.errors;
            $.each(responseErrors, function(index, value)
            {
                if (value.length != 0)
                {
                    $("#validation-errors").append('<div class="alert alert-error"><strong>'+ value +'</strong><div>');
                }
            });
            $("#validation-errors").show();
        } else {

          $('#user-avatar').attr('src',response.avatar);

        }
    }

4.处理上传的图片

回到UsersController.php中的avatarUpload方法,现在就可以处理上传上来的图片了:

public function avatarUpload()
    {
        $this->wrongTokenAjax();
        $file = Input::file('image');
        $input = array('image' => $file);
        $rules = array(
            'image' => 'image'
        );
        $validator = Validator::make($input, $rules);
        if ( $validator->fails() ) {
            return Response::json([
                'success' => false,
                'errors' => $validator->getMessageBag()->toArray()
            ]);

        }
        
        $destinationPath = 'uploads/';
        $filename = $file->getClientOriginalName();
        $file->move($destinationPath, $filename);
                return Response::json(
                    [
                        'success' => true,
                        'avatar' => asset($destinationPath.$filename),
                    ]
                );
            }

        

    }

注:在上传之前,确认在laravel的public/目录下创建了uploads/文件夹,并给以相应的权限,如:

sudo chmod -R 777 uploads/

在上面的avatarUpload方法中,有一个wrongTokenAjax方法,这是用来检验Laravel体系的token值的,同样是在UsersController.php中添加:

 public function wrongTokenAjax()
    {
        if ( Session::token() !== Request::get('_token') ) {
            $response = [
                'status' => false,
                'errors' => 'Wrong Token',
            ];

            return Response::json($response);
        }

    }

5.最后

到这里一个简单的Ajax上传图片的demo就完成了,在实际的开发中,我们还需要考虑以下几个问题:

  1. 根据用户的不同用户名或者用户id来创建不同的文件夹,这些都可以在avatarUpload方法中 $file->move($destinationPath, $filename)之前使用

    File::exists($username) or File::makeDirectory($username);
  2. 更新数据库中用户的avatar字段,大概是这样的:在avatarUpload方法返回数据之前,使用下面的类似语句:

    $user->avatar = your_avtar_upload_path;
    
    $user->save();
  3. 如果你还想更进一步改善体验,提供一些图片的裁剪和添加滤镜等功能,可以同时使用 Intervention/Image php包和Jcrop js图片裁剪实现,比如在:

    function showResponse(response)  {
    
    }

中,如果成功的返回图片,就在$('#user-avatar').attr('src',response.avatar)后执行:

 $('#user-avatar').Jcrop({
                aspectRatio: 1,
                onSelect: updateCoords,
                setSelect: [120,120,10,10]
                });

就可以在前端实现图片裁剪,然后将相应的裁剪数据如裁剪图片的height,width,x-align.y-align等传到后端处理就可以,使用Intervention/Image的话,在后端处理图片就是轻而易举的事情了!

Happy Hacking

本文由 JellyBool 创作, 转载和引用遵循 署名-非商业性使用 2.5 中国大陆 进行许可。

共有 22 条评论

v1tal
修改的评论也不能少于六个字哦!
wosjohn 回复 v1tal
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
v1tal
修改的评论也不能少于六个字哦!
v1tal
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
v1tal
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
lyon
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
apsana
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
apsana
修改的评论也不能少于六个字哦!
guanxi
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
xuan2429833524
修改的评论也不能少于六个字哦!
xuan2429833524
修改的评论也不能少于六个字哦!
xuan2429833524
修改的评论也不能少于六个字哦!
ak10181
修改的评论也不能少于六个字哦!
q8961152
修改的评论也不能少于六个字哦!
JellyBool 回复 q8961152
修改的评论也不能少于六个字哦!
UncleCaozy
修改的评论也不能少于六个字哦!