在編寫web程序的過程當中,常常會遇到一個經典的文件上傳場景:上傳頭像(圖片)。基於對最好的用戶體驗的追求,寫一下以前在項目中實如今Laravel項目中的Ajax
上傳頭像。php
在Laravel的routes.php
中設置路由:css
Route::get('/avatar/upload','UsersController@avatar'); Route::post('/avatar/upload','UsersController@avatarUpload');
在UsersController.php
中增長對應的avatar
和avatarUpload
這兩個方法,前者用來渲染視圖,後者處理實際上傳的圖像文件。html
public function avatar() { return view('users.avatar'); } public function avatarUpload() { //some codes to deal with upload avatar }
這其實就是在對應的users/
文件夾的avatar.blade.php
視圖文件中設置樣式,如下的HTML的各個標籤能夠根據本身的狀況設置class
和id
:前端
<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/:jquery
$(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); } }
回到UsersController.php
中的avatarUpload
方法,如今就能夠處理上傳上來的圖片了:laravel
public function avatar() { $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/
文件夾,並給以相應的權限,如:web
sudo chmod -R 777 uploads/
在上面的avatarUpload
方法中,有一個wrongTokenAjax
方法,這是用來檢驗Laravel體系的token
值的,一樣是在UsersController.php
中添加:ajax
public function wrongTokenAjax() { if ( Session::token() !== Request::get('_token') ) { $response = [ 'status' => false, 'errors' => 'Wrong Token', ]; return Response::json($response); } }
到這裏一個簡單的Ajax
上傳圖片的demo就完成了,在實際的開發中,咱們還須要考慮如下幾個問題:數據庫
根據用戶的不一樣用戶名或者用戶id來建立不一樣的文件夾,這些均可以在avatarUpload
方法中 $file->move($destinationPath, $filename)
以前使用json
File::exists($username) or File::makeDirectory($username);
更新數據庫中用戶的avatar
字段,大概是這樣的:在avatarUpload
方法返回數據以前,使用下面的相似語句:
$user->avatar = your_avtar_upload_path; $user->save();
若是你還想更進一步改善體驗,提供一些圖片的裁剪和添加濾鏡等功能,能夠同時使用 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