最近在處理後台資料時需要實現檔案上傳.考慮到對瀏覽器適配上採用Fine Uploader. Fine Uploader 採用ajax方式實現對檔案上傳.同時在瀏覽器中直接支援檔案拖拽[對瀏覽器版本有要求類似IE版本必須是9或是更高的IE10].在不同瀏覽器中提供統一使用者體驗.該組件基本覆蓋目前所有主流瀏覽器.同時沒有任何第三方組件依賴.相當Clear.在伺服器端已經覆蓋支援了ASP.NET/ColdFusion/Java/Node.js/Perl/PHP/Python. 對上傳細節類似限制檔案大小,檔案類型,檔案上傳的數量等通過統一介面以暴露選項方式操作.
雲棲社區下載地址 http://www.jb51.net/codes/70040.html
看到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檔案即可實現檔案上傳.大大簡化使用者引用和操作組件難度.
Fine Uploader特點如下:
Fine Uploader Features:
A:支援檔案上傳進度顯示.
B:檔案拖拽瀏覽器上傳方式
C:Ajax頁面無重新整理.
D:多檔案上傳.
F:跨瀏覽器.
E:跨後台伺服器端語言.
在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引用如下:
複製代碼 代碼如下:
<link href="static/css/fineuploader.css" rel="stylesheet">
<link href="static/css/bootstrap.min.css" rel="stylesheet">
這兩個檔案時必須引用的.fineuploader.css則是對應下載Fine Uploder源碼Client目錄下.fineuploder.css 提供JS指令碼中所需的CSS樣式,主要包括按鈕的樣式、進度顯示的樣式以及上傳結果的樣式.添加JavaScript檔案引用如下:
複製代碼 代碼如下:
<script src="static/script/fineupload/header.js"></script>
<script src="static/script/fineupload/util.js"></script>
<script src="static/script/fineupload/button.js"></script>
<script src="static/script/fineupload/handler.base.js"></script>
<script src="static/script/fineupload/handler.form.js"></script>
<script src="static/script/fineupload/handler.xhr.js"></script>
<script src="static/script/fineupload/uploader.basic.js"></script>
<script src="static/script/fineupload/dnd.js"></script>
<script src="static/script/fineupload/uploader.js"></script>
其中uploder.js和uploder.basic.js則是前端的所有上傳功能都在該指令碼中實現.必須引用.
同時添加client目錄下processing和loading兩張進度顯示所需要的動態圖片.該圖片都在fineuploder.css檔案調用.
在body添加如下Code:
複製代碼 代碼如下:
<div id="bootstrapped-fine-uploader"></div>
<script>
function createUploader() {
var uploader = new qq.FineUploader({
element: document.getElementById('bootstrapped-fine-uploader'),
request: {
endpoint: 'server/handlerfunction'
},
text: {
uploadButton: '<i class="icon-upload icon-white"></i> Click me now and upload a product image'
},
template:
'<div class="qq-uploader span12">' +
'<pre class="qq-upload-drop-area span12"><span>{dragZoneText}</span></pre>' +
'<div class="qq-upload-button btn btn-success" style="width: auto;">{uploadButtonText}</div>' +
'<span class="qq-drop-processing"><span>{dropProcessingText}</span>'+
'<span class="qq-drop-processing-spinner"></span></span>' +
'<ul class="qq-upload-list" style="margin-top: 10px; text-align: center;"></ul>' +
'</div>',
classes: {
success: 'alert alert-success',
fail: 'alert alert-error'
},
debug: true
});
}
window.onload = createUploader;
</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:該參數一般用來在執行上傳檔案操作前.在用戶端做一些驗證.驗證操作包含檔案格式.檔案大小.等添加格式如下:
複製代碼 代碼如下:
validation:
{
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
sizeLimit: 204800 // 200 kB = 200 * 1024 bytes
}
allowedExtensions控制上傳檔案的尾碼格式數組.
sizeLimit上傳檔案大小的上限,單位為byte的數值.瀏覽器不一定支援本設定.也可以在伺服器端裡設定.
minSizeLimit:上傳檔案大小的下限,單位為byte的數值.同上有些瀏覽器存在適配問題.建議統一在服務端設定.
另外針對qq.FineUploder對象在執行上傳操作整個過程.定義了五個用戶端可控做額外操作的事件.可以再callback參數下設定定義:
複製代碼 代碼如下:
callbacks:
{
onSubmit: function(id, fileName) {
$messages.append('<div id="file-' + id + '" class="alert" style="margin: 20px 0 0"></div>');
},
onUpload: function(id, fileName) {
$('#file-' + id).addClass('alert-info')
.html('<img src="client/loading.gif" alt="Initializing. Please hold."> ' +
'Initializing ' +
'“' + fileName + '”');
}
}
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方式發送給伺服器端.一般傳遞參數格式如下:
複製代碼 代碼如下:
params:
{
argument1: "value1",
argument2: "value2"
},
ok.這時基本關於Fine Uploader用戶端初始化和控制操作選項基本完成.當我們需要上傳操作時.如果IsAuto=false時可以通過已經定義qq.FineUploader對象的uploadStoreFiles()方式手工觸發上傳操作:
複製代碼 代碼如下:
$('#triggerUpload').click(function() {
uploader2.uploadStoredFiles();
});
如果我們此時點擊上傳會發現.則提示上傳失敗. 因為還沒有對上傳伺服器端做任何處理:
複製代碼 代碼如下:
request:
{
endpoint: 'server/handlerfunction'
},
這時我們需要在EndPoint指定處理檔案上傳的Php檔案[這裡是phpdemo].關於伺服器端如果你沒有已經成熟處理模組.還是推薦你使用官方Server目錄上.這裡我採用php環境則選中時php.php檔案.對應用戶端修改如下:
複製代碼 代碼如下:
request:
{
endpoint: 'controller/php.php'
}
開啟php.php發現在檔案頭部說明該檔案使用同時在檔案定義三個類用來分別處理XMLHttpRequest、FormPost、BasicPost方式檔案伺服器端處理.在檔案頂部注釋中:
複製代碼 代碼如下:
/****************************************
Example of how to use this uploader class...
You can uncomment the following lines (minus the require) to use
hese as your defaults.
// list of valid extensions, ex. array("jpeg", "xml", "bmp")
$allowedExtensions = array();
// max file size in bytes
$sizeLimit = 10 * 1024 * 1024;
//the input name set in the javascript
$inputName = 'qqfile'
require('valums-file-uploader/server/php.php');
$uploader = new qqFileUploader($allowedExtensions, $sizeLimit, $inputName);
// Call handleUpload() with the name of the folder, relative to PHP's getcwd()
$result = $uploader->handleUpload('uploads/');
// to pass data through iframe you will need to encode all html tags
header("Content-Type: text/plain");
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
/******************************************/
已經詳細說明如下Class調用方式.添加如下Php代碼即可簡單完成伺服器端處理:
複製代碼 代碼如下:
$allowedExtensions = array("jpeg", "jpg", "bmp", "png");
$sizeLimit = 10 * 1024 * 1024;
$uploader = new qqFileUploader($allowedExtensions, $sizeLimit);
$result = $uploader->handleUpload('uploads/'); //folder for uploaded files
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
allowExtensions則定義了允許上傳檔案的格式.
sizeLimit上限定義為10M.注意首先採用Phpinfo();方法輸出當前php環境配置.一般預設情況預設上傳檔案最大大小為2M.如果你需要上傳更大則修改php.ini檔案配置參數 這裡不再贅述.
uploder則是初始化qq.Fileuploder對象.並載入配置.
fineuploder調用處理上傳函數.並傳遞伺服器端儲存上傳檔案儲存體路徑.
echo想伺服器端輸出上傳結果.必須.不然用戶端接受不到指定responseJason參數用來判斷上傳後狀態.
在進一步看看伺服器端如何處理上傳的找到handleUpload函數定義.
複製代碼 代碼如下:
/**
* Handle the uploaded file
* @param string $uploadDirectory
* @param string $replaceOldFile=true
* @returns array('success'=>true) or array('error'=>'error message')
*/
function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
if (!is_writable($uploadDirectory)){
return array('error' => "Server error. Upload directory isn't writable.");
}
if (!$this->file){
return array('error' => 'No files were uploaded.');
}
$size = $this->file->getSize();
if ($size == 0) {
return array('error' => 'File is empty');
}
if ($size > $this->sizeLimit) {
return array('error' => 'File is too large');
}
$pathinfo = pathinfo($this->file->getName());
$filename = $pathinfo['filename'];
//$filename = md5(uniqid());
$ext = @$pathinfo['extension']; // hide notices if extension is empty
if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
$these = implode(', ', $this->allowedExtensions);
return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
}
$ext = ($ext == '') ? $ext : '.' . $ext;
if(!$replaceOldFile){
/// don't overwrite previous files that were uploaded
while (file_exists($uploadDirectory . DIRECTORY_SEPARATOR . $filename . $ext)) {
$filename .= rand(10, 99);
}
}
$this->uploadName = $filename . $ext;
if ($this->file->save($uploadDirectory . DIRECTORY_SEPARATOR . $filename . $ext)){
return array('success'=>true);
} else {
return array('error'=> 'Could not save uploaded file.' .
'The upload was cancelled, or server error encountered');
}
}
在調用這個處理函數時.需要注意的是.傳遞的URL儲存路徑需要時絕對的.所以需要對傳入路勁做一下格式化處理:
複製代碼 代碼如下:
$uploadDirectory = $_SERVER['DOCUMENT_ROOT']."DS".$uploadDirectory;
對於is_writeable檔案是否可寫的判斷.我個人認為還不夠詳細.is_writeable主要判斷檔案或目錄是否存在.並可寫才會返回true. 所以個人建議在is_writable前添加一個檔案是否存在.這樣更易於在用戶端判斷伺服器端檔案出錯具體的情況:
複製代碼 代碼如下:
if (!file_exists($uploadDirectory)) {
return array('error' => "Server error. Upload directory dones't exist.");
}
在儲存檔案操作前.可以看到.處理函數分別做了四次判斷.分別判斷了 上傳檔案的數量、檔案上傳的大小、檔案上傳大小是否超過上限、另外在上傳過程.如果我們多次想伺服器端上傳同一個檔案.發現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源碼角度分析其實現原理.
參考連結如下:
Fine Uploader
Fine Uploader Basic Upload Demo
Git Hub Fine Uploader Document and Code Sample