多種上傳圖片的方法

tags: 圖片上傳, multipart, 截圖上傳, file對象, FormData, 拖拽上傳圖片, dataTransfer, readAsDataURLjavascript

一個以下所示的發佈框,常常會出如今各類微博、社區、論壇站點上,這類發佈形式雖然沒有高級編輯器那樣能夠任意排版加工,但也知足了常見的表述觀點意見的要求,它一般搭配一些表情、文件上傳、分享網頁視頻等方式,來知足上述需求。最近我從事的一個項目中,就完成了以下圖示的發佈內容的需求,今天主要講一下其中圖片和附件的上傳發布方式。html

其實上傳的方式有不少種,本文將列舉需求中用到的幾種上傳方式。前端

1. 表單上傳

也就是用傳統的form表單來上傳,使用form表單的input[type=」file」]控件,能夠打開系統的文件選擇對話框,從而達到選擇文件並上傳的目的,它的好處是多瀏覽器兼容,可是在多圖上傳、分段上傳上等高級特性上就顯得力不從心。java

表單的格式以下:git

我列出表單上傳所需的關鍵幾點:github

  • method=」post」: 採用post方式提交數據ajax

  • enctype=」multipart/form-data」:採用multipart格式上傳文件,此時request頭會顯示 Content-Type:multipart/form-data; boundary=——WebKitFormBoundaryzr34cwJ67R95KQC9windows

  • action:標明上傳的服務端處理地址api

  • type=」file」:使用input的file控件上傳瀏覽器

  • accept屬性是HTML5的新屬性,它規定了可經過文件上傳提交的文件類型

  • 上傳的觸發事件能夠是:input[type=」file」]的onChange觸發,也能夠由一個獨立的按鈕的onClick使整個表單提交,此時還能夠用input[type=」hidden」]帶一些其它的參數,好比Token來源驗證等等。

2. Ajax無刷新上傳

ajax無刷新上傳的方式,本質上與表單上傳無異,只是把表單裏的內容提出來採用ajax提交,而且由前端決定請求結果回傳後的展現結果,不用像直接表單上傳那樣刷新和跳轉頁面。在這裏,咱們採用jQuery來做爲操做DOM和建立ajax提交的js基礎庫。

html代碼片斷以下:

javascript代碼片斷以下:

咱們使用了file控件的change來觸發上傳事件,固然你也可使用某個按鈕來觸發表單提交。提交數據時,我用到了FormData對象來發送二進制文件,FormData構造函數提供的append()方法,除了直接添加二進制文件還能夠附帶一些其它的參數,做爲XMLHttpRequest實例的參數提交給服務端。

以下是Firefox MDN對FormData的解釋。

XMLHttpRequest Level 2添加了一個新的接口FormData.利用FormData對象,咱們能夠經過JavaScript用一些鍵值對來模擬一系列表單控件,咱們還可使用XMLHttpRequest的send()方法來異步的提交這個」表單」.比起普通的ajax,使用FormData的最大優勢就是咱們能夠異步上傳一個二進制文件.
https://developer.mozilla.org/zh-CN/docs/Web/API/FormData

BTW: 使用jQuery提供的ajax方法來發送二進制文件,還須要附加兩個參數:

  • processData: false  // 不要對data參數進行序列化處理,默認爲true

  • contentType: false  // 不要設置Content-Type請求頭,由於文件數據是以 multipart/form-data 來編碼

3. flash上傳

不少時候上傳的需求都不是隻侷限於單圖上傳,並且須要顯示上傳進度、中斷上傳過程、大文件分段上傳等等,這時傳統的表單上傳沒法實現這些功能,因而產生了使用Flash上傳的方式,它採用Flash做爲一箇中間代理層,代替客戶端跟服務端通訊,此外,它也對客戶端的文件選擇方面擁有更多的控制權,比input[type=」file」]要大得多。

在這裏我使用了jQuery封裝好的uploadify插件來進行演示,通常這類插件都自帶了上傳用的Flash文件,由於跟服務端回傳的數據和展現跟客戶端的交互,都是Flash文件的接口跟插件來對接的。

<div id="file_upload">

html部分很簡單,預留一個hook後,插件會在這個節點內部建立Flash的object,而且還附帶建立了上傳進度、取消控件和多文件隊列展現等界面。


選擇一個文件後,html代碼以下所示:

 

更多的API和配置請參考jQuery.uploadify 官網APIs ( http://www.uploadify.com/documentation/ )
美中不足的是,mac下會對Flash有各類各樣的限制,甚至不支持,因此使用的時候也要慎重考慮。

4. 截圖粘貼上傳

目前只有較大的幾家SNS和微博類型的站點發布框實現了這個功能,本着業界良心和用戶至上的原則,咱們也在內外站點開發的早期上線了此功能,這次只是對上傳接口的改造,在這裏簡單的把上傳過程和用到的內容介紹一下。

首先,截圖粘貼上傳的核心思想是,監聽粘貼事件,而後獲取剪切板中的數據,若是是一張圖片,則觸發上傳事件。
代碼片斷以下:


從上面代碼能夠看出,上傳的過程都是同樣的,主要是獲取文件的方式。
當進行粘貼(右鍵paste/ctrl+v)操做時,觸發剪貼板事件’paste’,從系統剪切板獲取內容,而系統剪切板的數據在不一樣瀏覽器保存在不一樣的位置:

  • IE內核:windows.clipboardData

  • 其它:e.originalEvent.clipboardData

https://www.w3.org/TR/clipboard-apis/

5. 拖拽上傳

拖拽上傳的方式,支持的瀏覽器比較少,由於它用到了HTML5的兩個新的屬性(API)一個是Drag and Drop ( http://caniuse.com/#search=drag ),一個是File API ( http://caniuse.com/#search=file )

上傳域監聽拖拽的三個事件:dragEnter、dragOver和drop,分別對應拖拽至、拖拽時和釋放三個操做的處理機制,固然你也能夠監聽dragLeave事件。

HTML5的File API提供了一個FileList的接口,它能夠經過拖拽事件的e.dataTransfer.files來傳遞的文件信息,獲取本地文件列表信息。

File API在HTML5規範中只是草案,在 W3C 草案中,File 對象只包含文件名、文件類型和文件大小等只讀屬性。但部分瀏覽器在草案以外提供了一個名爲 FileReader 的對象,用以讀取文件內容,而且能夠監控讀取狀態,它提供的方法有: 「readAsBinaryString」 ,」readAsDataURL」 ,」readAsText」 ,」abort」 等。

參考MDN https://developer.mozilla.org/en-US/docs/Web/API/File

代碼片斷以下:

拖拽上傳過程當中的幾個關鍵點:

  • 在drop事件觸發後經過e.dataTransfer.files獲取拖拽文件列表,在jQuery中是e.originalEvent.dataTransfer.files

  • 拖拽上傳僅支持圖片,文件對象中file.type標識了文件類型

  • 因爲多是多圖拖拽,因此能夠遍歷圖片上傳,這裏用了Underscore的each方法

  • 這裏用readAsDataURL讀取文件內容爲二進制文件,你還能夠將其轉換爲Base64方式上傳,只是http協議裏面存在對非二進制數據的上傳大小限制爲2M。

  • 上傳的過程跟前面的方式相同,即:建立FormData對象併發起Ajax請求

總結

  1. 以上各類方式分別試用不一樣的場景,並沒有高下之分。

  2. 後面集中方式只有高級瀏覽器才支持,因此僅算是體驗上的加強。

  3. 上面的代碼僅是核心代碼片斷,如需運行還需補充參數,好比上傳地址,固然,也須要服務器的支持。代碼地址 ( https://github.com/moxiaohe/moxiaohe.github.io/issues/7 )

  4. 對於這些方式,阿里巴巴信息平臺的uxcore框架已經封裝了成型的組件且用在了咱們平常的項目中,歡迎使用。傳送門 uxcore-uploader ( http://uxco.re/components/uploader/ )

相關文章
相關標籤/搜索