日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

定制jQuery File Upload為微博式單文件上傳

 feimishiwo 2014-05-09

jQuery File Upload是一個(gè)非常優(yōu)秀的上傳組件,主要使用了XHR作為上傳方式,并且利用了相當(dāng)多的現(xiàn)代瀏覽器功能,所以可以實(shí)現(xiàn)諸如批量上傳、超大文件上傳、圖片預(yù)覽、拖拽上傳、上傳進(jìn)度顯示、跨域上傳等功能。

美中不足的是jQuery File Upload的默認(rèn)UI比較復(fù)雜,集成了全部功能,讓jQuery File Upload的定制變得比較繁瑣。

嘗試用jQuery File Upload制作了一個(gè)類似微博圖片上傳的單文件式上傳Demo,將一些要點(diǎn)記錄下來備忘。最終效果如下圖:

jQuery File Upload Demo

jQuery File Upload的最簡(jiǎn)模型

jQuery File Upload包含了一堆文件,首先需要弄清楚的是最核心的部分是哪些,根據(jù)官方的例子可以知道,一個(gè)最簡(jiǎn)單的jQuery File Upload上傳組件,必須包括以下文件:

  • jQuery核心庫(kù),建議使用jQuery 1.8以上版本
  • js/vendor/jquery.ui.widget.js : jQuery UI Widget
  • js/jquery.iframe-transport.js : 擴(kuò)展iframe數(shù)據(jù)傳輸
  • js/jquery.fileupload.js : jQuery File Upload核心類
  • js/cors/jquery.xdr-transport.js 在IE下應(yīng)載入此文件解決跨域問題

此時(shí)只需要加載一個(gè)上傳按鈕

<input id="fileupload" type="file" name="files[]" data-url="server/php/" multiple>

以及一行代碼

$('#fileupload').fileupload();

就完成了一個(gè)最基本的上傳組件。這個(gè)最簡(jiǎn)單的上傳組件可以將選中的文件以表單形式提交到data-url約定的URL,同時(shí)提供了足夠多的設(shè)置和基礎(chǔ)事件可供擴(kuò)展。

jQuery File Upload的簡(jiǎn)單擴(kuò)展

對(duì)于最簡(jiǎn)模型,稍加擴(kuò)展就可以實(shí)現(xiàn)一些比較常用的功能,比如可以在上傳完畢后可以顯示一個(gè)簡(jiǎn)單的結(jié)果:

$('#fileupload').fileupload({
    done: function (e, data) {
        $.each(data.result, function (index, file) {
            $('<p/>').text(file.name + ' uploaded').appendTo($("body"));
        });
    }
});

或者顯示上傳進(jìn)度,配合一些進(jìn)度條組件就可以構(gòu)成一個(gè)上傳進(jìn)度條

$('#fileupload').fileupload('option', {
    progressall: function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        console.log(progress + '%');
    }
});

等等。只要多閱讀手冊(cè)就可以配合項(xiàng)目做更具體的擴(kuò)展開發(fā)。

XHR響應(yīng)為Json時(shí)IE的下載BUG

這里需要特別注意的是,由于jQuery File Upload都是采用XHR在傳遞數(shù)據(jù),服務(wù)器端返回的通常是JSON格式的響應(yīng),但是IE會(huì)將這些JSON響應(yīng)誤認(rèn)為是文件傳輸,然后直接彈出下載框詢問是否需要下載。

解決這個(gè)問題的方法是必須將相應(yīng)的Http Head從

Content-Type: application/json

更改為

Content-Type: text/plain

具體的實(shí)現(xiàn)根據(jù)服務(wù)端不同有所區(qū)別,比如ZF2中可以在Controller中這樣寫:

 $this->getServiceLocator()->get('Application')->getEventManager()->attach(\Zend\Mvc\MvcEvent::EVENT_RENDER, function($event){
     $event->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');
 }, -10000);

這也是我在stackoverflow上的對(duì)ZF2更改最終響應(yīng)類型的一個(gè)回答

jQuery File Upload UI的構(gòu)成與說明

為了引入更多功能,jQuery File Upload在上面最簡(jiǎn)模型的基礎(chǔ)上又實(shí)現(xiàn)了一套jQuery File Upload UI,也就是官方給出的最終Demo,這套UI額外提供了以下功能:

  • 最大/最小文件限定 Options.maxFileSize / Options.mixFileSize
  • 文件類型限定,通過正則表達(dá)式檢測(cè)文件名實(shí)現(xiàn) Options.acceptFileTypes
  • 選擇文件后自動(dòng)上傳 Options.autoUpload
  • 上傳文件數(shù)量限制,通過上傳后將選擇文件按鈕置為Disabled實(shí)現(xiàn) Options.maxNumberOfFiles
  • 上傳模板,就是選擇文件后顯示預(yù)覽的html代碼 Options.uploadTemplate
  • 下載模板,當(dāng)文件上傳完畢后顯示的html代碼 Options.downloadTemplate

等等,同時(shí)還增加了一系列新的接口和事件,具體都可以查閱官方手冊(cè)。

具體對(duì)應(yīng)到文件為:

  • JavaScript-Templates : JS模板引擎
  • JavaScript-Load-Image : 圖片預(yù)覽功能
  • js/jquery.fileupload-ui.js & css/jquery.fileupload-ui.css : UI核心類,CSS可以替換舊式的上傳控件為統(tǒng)一的按鈕
  • js/jquery.fileupload-fp.js:進(jìn)度條擴(kuò)展功能

也許正是因?yàn)楦郊庸δ芴?,各功能之間耦合非常重,jQuery File Upload UI顯得不夠友好,主要體現(xiàn)在:

  • 上述功能均無法拆分,必須統(tǒng)一全部加載
  • 各功能需要界面存在相應(yīng)元素,如果缺少某些元素,包括JS模板內(nèi)的元素,整個(gè)UI無法正常工作
  • JS模板引擎對(duì)標(biāo)簽配對(duì)非常嚴(yán)格,標(biāo)簽如果遺漏也有可能引起UI無法正常工作

所以經(jīng)驗(yàn)之談是,在定制jQuery File Upload UI時(shí),如果UI無法工作。首先檢查js文件是否全部加載,然后檢查頁(yè)面元素是否齊全,再次檢查JS模板標(biāo)簽是否嚴(yán)格配對(duì),最后還可以查看頁(yè)面是否有重復(fù)調(diào)用fileupload()方法。

jQuery File Upload UI構(gòu)成元素

UI的部件都是硬編碼的HTML class,無法更改。核心的幾個(gè)部件為

全局控制按鈕 (必須)

    <div class="fileupload-buttonbar">
            <span class="fileinput-button"><input type="file" name="files[]" multiple></span>
            <button type="submit" class="start">Start upload</button>
            <button type="reset" class="cancel">Cancel upload</button>
            <button type="button" class="delete">Delete</button>
            <input type="checkbox" class="toggle">
    </div>

最外層容器為.fileupload-buttonbar,內(nèi)部包含

  • 文件選擇按鈕 .fileinput-button (必須),內(nèi)部必須包裹一個(gè)input:file
  • 開始上傳按鈕 .start
  • 取消上傳按鈕 .cancel
  • 刪除按鈕 .delete
  • 文件勾選按鈕 .toggle

整體上傳進(jìn)度 (可選)

<div class="fileupload-progress">
    <div class="progress">
        <div class="bar" style="width:0%;"></div>
    </div>
    <div class="progress-extended"></div>
</div>

最外層容器為.fileupload-progress,內(nèi)部包含

  • 上傳進(jìn)度條容器.progress
  • 上傳進(jìn)度條 .bar
  • 上傳進(jìn)度文本 .progress-extended

文件顯示容器 (必須)

<div class="files"></div>

.file容器是最重要的UI部件,上傳時(shí)的文件預(yù)覽模板以及上傳完畢后的文件顯示模板都將顯示在這里。

文件預(yù)覽模板 (必須)

<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<div class="template-upload">
    {% if (file.error) { %}
        <div class="error">{%=file.error%}</div>
    {% } else { %}
    <div class="preview"><span class="fade"></span></div>
    <div class="name"><span>{%=file.name%}</span></div>
    <div class="size"><span>{%=o.formatFileSize(file.size)%}</span></div>
    <div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" style="height:5px;"><div class="bar" style="width:0%;"></div></div>
    <span class="start">
        {% if (!o.options.autoUpload) { %}
            <button>Start Upload</button>
        {% } %}
    </span>
    {% } %}
    <span class="cancel"><button>Cancel</button></span>
</div>
{% } %}
</script>

這部分邏輯不難讀懂,由于文件選擇是多選的,所以被選擇文件一開始以數(shù)組方式存放,循環(huán)輸出。即使我們加入最大文件只能上傳一個(gè),這里得到的仍然是數(shù)組形式。

當(dāng)文件有任何錯(cuò)誤時(shí),如文件類型被禁止,文件大小不符合約定,會(huì)得到file.error。文件檢測(cè)沒有問題,則可以用以下元素控制當(dāng)前文件:

  • 開始上傳當(dāng)前文件按鈕.start (必須)
  • 取消上傳當(dāng)前文件按鈕.cancel (可選)
  • 當(dāng)前文件上傳進(jìn)度.progress (可選)

上傳后文件回調(diào)顯示模板 (必須)

<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<div class="template-download">
    {% if (file.error) { %}
        <div class="error">{%=file.error%}</div>
        <span class="cancel"><button class="btn btn-block"><i class="icon-ban-circle"></i>Cancel</span>
    {% } else { %}
    <div class="preview"><img src="{%=file.thumbnail_url%}"></div>
    <div class="name"><span>{%=file.name%}</span></div>
    <div class="size"><span>{%=o.formatFileSize(file.size)%}</span></div>
    <div class="delete"><button data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">Delete</button>
    </div>
    {% } %}
</div>
{% } %}
</script>

這一部分的o.files完全來自服務(wù)器端的json響應(yīng),所以模板內(nèi)容可以自由發(fā)揮。唯一被定制的元素為刪除按鈕.delete。 點(diǎn)擊這個(gè)按鈕會(huì)向按鈕中指定的url發(fā)送請(qǐng)求,比如

<div class="delete"><button data-type="DELETE" data-url="/file/1">Delete</button></div>

點(diǎn)擊后則會(huì)用DELETE方式發(fā)送HTTP請(qǐng)求

DELETE /file/1

jQuery File Upload UI工作流程

有了上面羅列的UI元素,就可以拼湊出一個(gè)簡(jiǎn)單的jQuery File Upload UI工作流程:

  1. 用戶點(diǎn)擊.fileinput-button選擇要上傳的文件(多個(gè))
  2. 文件選擇后,文件信息被整理為數(shù)組置入文件預(yù)覽模板#template-upload
  3. 模板引擎循環(huán)處理文件信息并生成模板.template-upload
  4. 每生成一個(gè)模板,模板就被插入到文件顯示容器.files的最后。
  5. 用戶點(diǎn)擊上傳按鈕.start上傳,文件信息被轉(zhuǎn)換為XHR請(qǐng)求至服務(wù)器端
  6. UI獲得服務(wù)器端生成JSON響應(yīng)文件
  7. JSON響應(yīng)信息也被整理成數(shù)組置入回調(diào)顯示模板#template-download
  8. 模板引擎循環(huán)處理文件信息并生成模板.template-download
  9. 每生成一個(gè)模板,會(huì)將此模板替換對(duì)應(yīng)的.template-upload部分

定制過程

有了上面的基礎(chǔ),要個(gè)性化的定制jQuery File Upload就簡(jiǎn)單了很多:

限制文件類型

由于沒有使用Flash空間,上傳的文件選擇框是無法限制文件類型的,所以所謂的限制文件類型,只能讓用戶選擇文件之后,用file.error顯示一個(gè)錯(cuò)誤信息。例如本次需要限定可上傳的文件為圖片,那么Options指定:

acceptFileTypes:  /(\.|\/)(gif|jpe?g|png)$/i

即可。

在Google Chrome瀏覽器中,可以用input:file原生支持文件類型限定,可以配合使用:

<input type="file" name="upload[]"  accept="image/png, image/gif, image/jpg, image/jpeg">

不過在客戶端做再多的限定也只是提升用戶體驗(yàn),不能真正保證安全性,所以不要忘記了在服務(wù)器端做同樣的類型檢測(cè)。

文件數(shù)量限制

只需在Options指定

maxNumberOfFiles : 1

即可。jQuery File Upload UI的處理方式是當(dāng)用戶上傳一個(gè)文件后,文件選擇按鈕被置為Disabled。

這同樣只是客戶端的小把戲,真正想要嚴(yán)格的約束用戶只能上傳一個(gè)文件還是需要在服務(wù)器端通過Session做更加復(fù)雜的控制。

文件大小限制

Options中指定

maxFileSize: 5000000

即只允許單文件最大5MB。

Firefox disable bug

在Firefox環(huán)境下測(cè)試是,發(fā)現(xiàn)如果將文件數(shù)量限制為1,選擇一次文件,刷新頁(yè)面之后文件選擇按鈕會(huì)莫名其妙的被加上一個(gè)Disabled屬性,導(dǎo)致無法點(diǎn)擊。所以最終我們的初始化代碼為:

var uploader = $("#fileupload");
uploader.fileupload({
    dataType: 'json',
    autoUpload: false,
    acceptFileTypes:  /(\.|\/)(gif|jpe?g|png)$/i,
    maxNumberOfFiles : 1,
    maxFileSize: 5000000 
});
uploader.find("input:file").removeAttr('disabled');

最后就是界面的一些調(diào)整,完整代碼在EvaEngine的File模塊下,點(diǎn)擊查看.


 Tags : jQuery 上傳 jQuery File Upload 插件

Follow :

Donate:Buy me a coffee  | 文章有幫助,可以請(qǐng)我喝杯咖啡

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多