最近在處理後臺數據時須要實現文件上傳.考慮到對瀏覽器適配上採用Fine Uploader. Fine Uploader 採用ajax方式實現對文件上傳.同時在瀏覽器中直接支持文件拖拽[對瀏覽器版本有要求相似IE版本必須是9或是更高的IE10].在不一樣瀏覽器中提供統一用戶體驗.該組件基本覆蓋目前全部主流瀏覽器.同時沒有任何第三方組件依賴.至關Clear.在服務器端已經覆蓋支持了ASP.NET/ColdFusion/Java/Node.js/Perl/PHP/Python. 對上傳細節相似限制文件大小,文件類型,文件上傳的數量等經過統一接口以暴露選項方式操做.javascript
看到Github 上Fine Uploader 按照官方的說法. Fine Uploader前身是Ajax Upload. 新版本Fine Uploader主要添加一些新特性.從1.0版本發佈的Realse Note來看.兩者最大的區別在於.Fine Uploder不在基於Jquery組件.而某些細節處理也更加統一嚴格.相似返回值所有統一爲Json格式.對後臺服務器操做和前端Dom對象一些操做Code所有集中Js Script腳本文件中.這樣集成使Fine Uploader組件使用很是簡單.只須要添加一個CSS+JavaScript文件便可實現文件上傳.大大簡化用戶引用和操做組件難度.php
Fine Uploader特色以下:css
Fine Uploader Features:html
A:支持文件上傳進度顯示.前端
B:文件拖拽瀏覽器上傳方式java
C:Ajax頁面無刷新.git
D:多文件上傳.github
F:跨瀏覽器.ajax
E:跨後臺服務器端語言.json
在Git Hub上Fine Uploader上下載打包源碼,在Php Designer 8中打開其源碼能夠看到其源碼結構以下:
在根目錄中能夠看到Client客戶端調用須要使用文件.Server目錄則是對應不一樣語言Perl/Php/Asp.net[VB]等版本實現.test目錄則有包含一個完整本地Sample Demo.可供參考.
如何快速構建一個簡單Demo? 其實官方在Basic-Demo-Page上已經給出一個簡單的演示.這裏基於Bootstrap方式構建.
首先新建一個Html空白頁面.命名FineUploderDemo.html.添加以下CSS引用以下:
1: <link href="static/css/fineuploader.css" rel="stylesheet">
2: <link href="static/css/bootstrap.min.css" rel="stylesheet">
這兩個文件時必須引用的.fineuploader.css則是對應下載Fine Uploder源碼Client目錄下.fineuploder.css 提供JS腳本中所需的CSS樣式,主要包括按鈕的樣式、進度顯示的樣式以及上傳結果的樣式.添加JavaScript文件引用以下:
1: <script src="static/script/fineupload/header.js"></script>
2: <script src="static/script/fineupload/util.js"></script>
3: <script src="static/script/fineupload/button.js"></script>
4: <script src="static/script/fineupload/handler.base.js"></script>
5: <script src="static/script/fineupload/handler.form.js"></script>
6: <script src="static/script/fineupload/handler.xhr.js"></script>
7: <script src="static/script/fineupload/uploader.basic.js"></script>
8: <script src="static/script/fineupload/dnd.js"></script>
9: <script src="static/script/fineupload/uploader.js"></script>
其中uploder.js和uploder.basic.js則是前端的全部上傳功能都在該腳本中實現.必須引用.
同時添加client目錄下processing和loading兩張進度顯示所須要的動態圖片.該圖片都在fineuploder.css文件調用.
在body添加以下Code:
1: <div id="bootstrapped-fine-uploader"></div>
2: <script>
3: function createUploader() {
4: var uploader = new qq.FineUploader({
5: element: document.getElementById('bootstrapped-fine-uploader'),
6: request: {
7: endpoint: 'server/handlerfunction'
8: },
9: text: {
10: uploadButton: '<i class="icon-upload icon-white"></i> Click me now and upload a product image'
11: },
12: template:
13: '<div class="qq-uploader span12">' +
14: '<pre class="qq-upload-drop-area span12"><span>{dragZoneText}</span></pre>' +
15: '<div class="qq-upload-button btn btn-success" style="width: auto;">{uploadButtonText}</div>' +
16: '<span class="qq-drop-processing"><span>{dropProcessingText}</span>'+
17: '<span class="qq-drop-processing-spinner"></span></span>' +
18: '<ul class="qq-upload-list" style="margin-top: 10px; text-align: center;"></ul>' +
19: '</div>',
20: classes: {
21: success: 'alert alert-success',
22: fail: 'alert alert-error'
23: },
24: debug: true
25: });
26: }
27:
28: window.onload = createUploader;
29: </script>
這是基於Bootstrap實現對Fine Uploader最簡單的前端調用.前端通常須要作兩件事A:添加Css+Js文件引用.B:在Js中實例化qq.FineUploder對象.運行效果以下:
查看JS構建qq.Fineuploader對象建立過程.首先指定Fine Uploader插件的Dom元素.經過Dom獲取操做.request則是對應服務器端實現文件路徑.在這建議不要本身構建服務器端處理.而是直接採用官方提供的實現文件修改便可.template則是對應上傳文件添加內容模版也能夠本身修改.debug是一個布爾值.用來控制是否使用瀏覽器的控制檯打印Fine Uploader的調試信息,默認爲false.
qq.FineUploader對象還有以下控制參數:
validation:該參數通常用來在執行上傳文件操做前.在客戶端作一些驗證.驗證操做包含文件格式.文件大小.等添加格式以下:
1: validation:
2: {
3: allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
4: sizeLimit: 204800 // 200 kB = 200 * 1024 bytes
5: }
allowedExtensions控制上傳文件的後綴格式數組.
sizeLimit上傳文件大小的上限,單位爲byte的數值.瀏覽器不必定支持本設置.也能夠在服務器端裏設置.
minSizeLimit:上傳文件大小的下限,單位爲byte的數值.同上有些瀏覽器存在適配問題.建議統一在服務端設置.
另外針對qq.FineUploder對象在執行上傳操做整個過程.定義了五個客戶端可控作額外操做的事件.能夠再callback參數下設置定義:
1: callbacks:
2: {
3: onSubmit: function(id, fileName) {
4: $messages.append('<div id="file-' + id + '" class="alert" style="margin: 20px 0 0"></div>');
5: },
6: onUpload: function(id, fileName) {
7: $('#file-' + id).addClass('alert-info')
8: .html('<img src="client/loading.gif" alt="Initializing. Please hold."> ' +
9: 'Initializing ' +
10: '「' + fileName + '」');
11: }
12: }
onSubmit事件:文件開始提交.調用參數格式以下:onSubmit: function(id, fileName) {}.
onUpload事件: 文件開始上傳.調用參數格式以下:onUpload: function(id, fileName) {}.
onProgress事件: 文件正在上傳.調用參數格式以下:onProgress: function(id, fileName, loaded, total) {}.
onComplete事件: 文件上傳成功. 調用參數格式以下:onComplete: function(id, fileName, responseJSON) {}.
onCancel事件: 取消文件上傳.調用參數格式以下:onCancel: function(id, fileName) {}.
如上五個事件基本覆蓋整個上傳文件操做中全部過程.徹底以開放的形式能夠再客戶端操做.關於調用如上事件參數說明以下:
Id:表示第幾個開始上傳的文件.Fine Uploder定義是默認從0開始計數.
fileName:上傳文件的文件名.
loaded:表示已經上傳到服務器端數據的大小[byte].
total: 須要上傳文件的大小.
responseJSON: 用來在上傳操做完成後返回的Json格式的數據.經過Jquery反序列化出來對象.其中包含一個IsSuccess屬性用來判斷這次上傳是否成功.
若是你想在上傳過程向服務器端傳遞數據.能夠經過以下參數控制:
params:用來向服務器端傳遞數據.注意params採用key-value的數組存儲.採用Post方式發送給服務器端.通常傳遞參數格式以下:
1: params:
2: {
3: argument1: "value1",
4: argument2: "value2"
5: },
ok.這時基本關於Fine Uploader客戶端初始化和控制操做選項基本完成.當咱們須要上傳操做時.若是IsAuto=false時能夠經過已經定義qq.FineUploader對象的uploadStoreFiles()方式手工觸發上傳操做:
1: $('#triggerUpload').click(function() {
2: uploader2.uploadStoredFiles();
3: });
若是咱們此時點擊上傳會發現.則提示上傳失敗. 由於尚未對上傳服務器端作任何處理:
1: request:
2: {
3: endpoint: 'server/handlerfunction'
4: },
這時咱們須要在EndPoint指定處理文件上傳的Php文件[這裏是phpdemo].關於服務器端若是你沒有已經成熟處理模塊.仍是推薦你使用官方Server目錄上.這裏我採用php環境則選中時php.php文件.對應客戶端修改以下:
1: request:
2: {
3: endpoint: 'controller/php.php'
4: }
打開php.php發如今文件頭部說明該文件使用同時在文件定義三個類用來分別處理XMLHttpRequest、FormPost、BasicPost方式文件服務器端處理.在文件頂部註釋中:
1: /****************************************
2: Example of how to use this uploader class...
3: You can uncomment the following lines (minus the require) to use
4: hese as your defaults.
5:
6: // list of valid extensions, ex. array("jpeg", "xml", "bmp")
7: $allowedExtensions = array();
8: // max file size in bytes
9: $sizeLimit = 10 * 1024 * 1024;
10: //the input name set in the javascript
11: $inputName = 'qqfile'
12:
13: require('valums-file-uploader/server/php.php');
14: $uploader = new qqFileUploader($allowedExtensions, $sizeLimit, $inputName);
15:
16: // Call handleUpload() with the name of the folder, relative to PHP's getcwd()
17: $result = $uploader->handleUpload('uploads/');
18:
19: // to pass data through iframe you will need to encode all html tags
20: header("Content-Type: text/plain");
21: echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
22:
23: /******************************************/
已經詳細說明以下Class調用方式.添加以下Php代碼便可簡單完成服務器端處理:
1: $allowedExtensions = array("jpeg", "jpg", "bmp", "png");
2: $sizeLimit = 10 * 1024 * 1024;
3: $uploader = new qqFileUploader($allowedExtensions, $sizeLimit);
4: $result = $uploader->handleUpload('uploads/'); //folder for uploaded files
5: echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
allowExtensions則定義了容許上傳文件的格式.
sizeLimit上限定義爲10M.注意首先採用Phpinfo();方法輸出當前php環境配置.通常默認狀況默認上傳文件最大大小爲2M.若是你須要上傳更大則修改php.ini文件配置參數 這裏再也不贅述.
uploder則是初始化qq.Fileuploder對象.並加載配置.
fineuploder調用處理上傳函數.並傳遞服務器端存儲上傳文件存儲路徑.
echo想服務器端輸出上傳結果.必須.否則客戶端接受不到指定responseJason參數用來判斷上傳後狀態.
在進一步看看服務器端如何處理上傳的找到handleUpload函數定義.
1: /**
2: * Handle the uploaded file
3: * @param string $uploadDirectory
4: * @param string $replaceOldFile=true
5: * @returns array('success'=>true) or array('error'=>'error message')
6: */
7: function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
8: if (!is_writable($uploadDirectory)){
9: return array('error' => "Server error. Upload directory isn't writable.");
10: }
11:
12: if (!$this->file){
13: return array('error' => 'No files were uploaded.');
14: }
15:
16: $size = $this->file->getSize();
17:
18: if ($size == 0) {
19: return array('error' => 'File is empty');
20: }
21:
22: if ($size > $this->sizeLimit) {
23: return array('error' => 'File is too large');
24: }
25:
26: $pathinfo = pathinfo($this->file->getName());
27: $filename = $pathinfo['filename'];
28: //$filename = md5(uniqid());
29: $ext = @$pathinfo['extension']; // hide notices if extension is empty
30:
31: if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
32: $these = implode(', ', $this->allowedExtensions);
33: return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
34: }
35:
36: $ext = ($ext == '') ? $ext : '.' . $ext;
37:
38: if(!$replaceOldFile){
39: /// don't overwrite previous files that were uploaded
40: while (file_exists($uploadDirectory . DIRECTORY_SEPARATOR . $filename . $ext)) {
41: $filename .= rand(10, 99);
42: }
43: }
44:
45: $this->uploadName = $filename . $ext;
46:
47: if ($this->file->save($uploadDirectory . DIRECTORY_SEPARATOR . $filename . $ext)){
48: return array('success'=>true);
49: } else {
50: return array('error'=> 'Could not save uploaded file.' .
51: 'The upload was cancelled, or server error encountered');
52: }
53:
54: }
在調用這個處理函數時.須要注意的是.傳遞的URL存儲路徑須要時絕對的.因此須要對傳入路勁作一下格式化處理:
1: $uploadDirectory = $_SERVER['DOCUMENT_ROOT']."DS".$uploadDirectory;
對於is_writeable文件是否可寫的判斷.我我的認爲還不夠詳細.is_writeable主要判斷文件或目錄是否存在.並可寫纔會返回true. 因此我的建議在is_writable前添加一個文件是否存在.這樣更易於在客戶端判斷服務器端文件出錯具體的狀況:
1: if (!file_exists($uploadDirectory)) {
2: return array('error' => "Server error. Upload directory dones't exist.");
3: }
在保存文件操做前.能夠看到.處理函數分別作了四次判斷.分別判斷了 上傳文件的數量、文件上傳的大小、文件上傳大小是否超過上限、另外在上傳過程.若是咱們屢次想服務器端上傳同一個文件.發現Fine Uploder處理方式是.並不是是重寫.而是從10-99隨機一個數字重寫命名該文件.並保存到目錄下.當保存文件成功後.則想服務器端返回一個Json數據其中包含IsSuccess來指定這次上傳操做是否操做成功. IsSuccess參數做爲客戶端判斷此時操做惟一參數.
在上傳操做過程發信不少出現「increase post_max_size and upload_max_filesize to 10M」錯誤,其實針對這個問題.主要是上傳文件配置超過php環境默認的2M.須要在php.ini文件中把post_max_size和upload_max_filesize兩項的值改到10M以上,而後重啓Apache便可.或是參考Php官網針對配置說明 修改php.ini配置文件.
至此整個Fine Uploader配置流程已經所有完成.點擊選擇文件時.會以下效果:
提示上傳成功.固然更多的請參考官方給出演示demo.如上從Fine Uploader源碼角度分析其實現原理.
參考連接以下: