上週作一個關於移動端圖片壓縮上傳的功能。期間踩了幾個坑,在此總結下。javascript
大致的思路是,部分API的兼容性請參照caniuse:html
blob對象
,或者是file對象
,將圖片轉化爲data uri
的形式。canvas
,在頁面上新建一個畫布,利用canvas
提供的API,將圖片畫入這個畫布當中。canvas.toDataURL()
,進行圖片的壓縮,獲得圖片的data uri
的值步驟1當中,在進行圖片壓縮前,仍是對圖片大小作了判斷的,若是圖片大小大於200KB時,是直接進行圖片上傳,不進行圖片的壓縮,若是圖片的大小是大於200KB,則是先進行圖片的壓縮再上傳:html5
<input type="file" id="choose" accept="image/*">
var fileChooser = document.getElementById("choose"), maxSize = 200 * 1024; //200KB fileChoose.change = function() { var file = this.files[0], //讀取文件 reader = new FileReader(); reader.onload = function() { var result = this.result, //result爲data url的形式 img = new Image(), img.src = result; if(result.length < maxSize) { imgUpload(result); //圖片直接上傳 } else { var data = compress(img); //圖片首先進行壓縮 imgUpload(data); //圖片上傳 } } reader.readAsDataURL(file); }
步驟2,3:java
var canvas = document.createElement('canvas'), ctx = canvas.getContext('2d'); function compress(img) { canvas.width = img.width; canvas.height = img.height; //利用canvas進行繪圖 //將原來圖片的質量壓縮到原先的0.2倍。 var data = canvas.toDataURL('image/jpeg', 0.2); //data url的形式 return data; }
在利用canvas進行繪圖的過程當中,IOS圖片上傳過程當中,存在着這樣的問題:android
(使用了binaryajax.js)
,方便獲取圖片的exif信息
,經過獲取exif的信息
來肯定圖片旋轉的角度(使用了exif.js)
,而後再進行圖片相應的旋轉處理。解決方法請戳我 IOS
中,當圖片的大小大於 2MB時,會出現圖片壓扁的狀況,這個時候須要重置圖片的比例。解決方法請戳我 FileReader
的bug: FileReader
讀取的圖片轉化爲Base64時,字符串爲空,具體的問題描述請戳我 步驟4,文件上傳有2種方式:ios
方式1能夠經過xhr ajax或者xhr2 FormData進行提交。git
方法2這裏就有個大坑了。具體描述請戳我github
簡單點說就是:Blob對象
是沒法注入到FormData對象
當中的。web
當你拿到了圖片的data uri數據
後,將其轉化爲Blob
數據類型ajax
var ndata = compress(img); ndata = window.atob(ndata); //將base64格式的數據進行解碼 //新建一個buffer對象,用以存儲圖片數據 var buffer = new Uint8Array(ndata.length); for(var i = 0; i < text.length; i++) { buffer[i] = ndata.charCodeAt(i); } //將buffer對象轉化爲Blob數據類型 var blob = getBlob([buffer]); var fd = new FormData(), xhr = new XMLHttpRequest(); fd.append('file', blob); xhr.open('post', url); xhr.onreadystatechange = function() { //do something } xhr.send(fd);
在新建Blob對象
中有須要進行兼容性的處理,特別是對於不支持FormData
上傳blob
的andriod機的兼容性處理。具體的方法請戳我
主要實現的細節是經過重寫HTTP請求。
在安卓機器中,部分4.x
的機型, 在webview
裏面對file
對象進行了閹割,好比你拿不到file.type
的值。
Android4.4
下<input type="file">
因爲系統WebView
的openFileChooser
接口更改,致使沒法選擇文件,從而致使沒法上傳文件. bug描述請戳我