移動端 H5 圖片壓縮上傳
移動端H5圖片壓縮上傳
大體的思路是,部分API的兼容性請參照 caniuse :
- 利用 FileReader ,讀取 blob對象 ,或者是 file對象 ,將圖片轉化為 data uri 的形式。
- 使用 canvas ,在頁面上新建一個畫布,利用 canvas 提供的API,將圖片畫入這個畫布當中。
- 利用 canvas.toDataURL() ,進行圖片的壓縮,得到圖片的 data uri 的值
- 上傳文件。
步驟1當中,在進行圖片壓縮前,還是對圖片大小做了判斷的,如果圖片大小大于200KB時,是直接進行圖片上傳,不進行圖片的壓縮,如果圖片的大小是大于200KB,則是先進行圖片的壓縮再上傳:
<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); }</pre>
步驟2,3:
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圖片上傳過程中,存在著這樣的問題:
- 當你豎著拿手機的時候,拍完照,上傳圖片時,會出現照片自動旋轉的情況,而橫著拍照并上傳圖片時不會出現這個問題。這個時候如果想糾正圖片自動旋轉的情況,將圖片轉化為二進制的數據 (使用了binaryajax.js) ,方便獲取圖片的 exif信息 ,通過獲取 exif的信息 來確定圖片旋轉的角度 (使用了exif.js) ,然后再進行圖片相應的旋轉處理。
- 在 IOS 中,當圖片的大小大于 2MB時,會出現圖片壓扁的情況,這個時候需要重置圖片的比例。
- 利用FileReader,讀取圖片的過程需要花費一定時間,將圖片數據注入到canvas畫布中需要一定時間,圖片壓縮的過程中,圖片越大,CPU計算消耗的時間也越長,可能會出現頓卡的情況。總之,就是這個過程當中需要花費一定時間。
- IOS8.1的版本中有個 FileReader 的bug: FileReader 讀取的圖片轉化為Base64時,字符串為空,, 遇到這個情況的話- - 還是老老實實把圖片不做壓縮處理扔給服務端吧.
步驟4,文件上傳有2種方式:
- 將圖片轉化為 base64
- 將圖片數據轉為 Blob對象 ,使用 FormData 上傳文件
方式1可以通過 xhr ajax 或者 xhr2 FormData 進行提交。
方法2這里就有個大坑了。
簡單點說就是: Blob對象 是無法注入到 FormData對象 當中的。
當你拿到了圖片的 data uri數據 后,將其轉化為 Blob 數據類型
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請求。
2月19日更新
在安卓機器中, 部分機型不支持 JPEG 格式的圖片導出, 在 fex-team 提供的 webuploader 插件當中有個 jpegencoder.js 和 androidpatch.js 插件主要是解決這個問題, 不過在部分 4.x 的機型, 在 webview 里面對 file 對象進行了閹割,比如你拿不到 file.type 的值。 唉- -。
2月22日更新
Android4.4 下 <input type="file"> 由于系統 WebView 的 openFileChooser 接口更改,導致無法選擇文件,從而導致無法上傳文件.
使用
npm install npm run build
- 支持AMD, CMD模塊化的引入方式
- 也可通過外鏈
canvasResize(this.files[0], { crop: false, // 是否裁剪 quality: 0.9, // 壓縮質量 0 - 1 rotate: 0, // 旋轉角度 callback(baseStr) { console.log(baseStr.length) } })
Some Tips
- 在使用 FormData 進行文件上傳的時候,沒有將圖片文件轉化為 blob ,而是轉為了 base64 ,主要是考慮到部分機型的兼容性的問題。
- 在遇到一些是由于 native 端上導致的問題的時候,比如在安卓 4.4.x 的部分機型(主要集中在原生的系統,部門國產機,對 openFileChooser 做過兼容)當中無法喚起選擇圖片或拍照的接口, 這個時候還是讓 native 的同學給你提供 bridge 去完成圖片的壓縮和轉碼吧, 然后你再拿著端上給壓縮好的圖片去上傳吧。
- 封裝好的庫中沒有提供裁剪的選項,如果需要有這方面的需求,請在 src/canvasResize.js 里面做相應的修改(讀讀源碼也挺好- -)。
使用到的庫
來自:https://github.com/CommanderXL/imgResize/blob/master/README.md
本文由用戶 nkslixin 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!