這段時間在工做中碰到一個須要在h5裁剪圖像,而後直傳阿里雲的需求。圖中遇到了一些小問題,分享出來你們都看看。javascript
h5裁剪圖像:cropper.js是一個神器啊關於用法,網上能夠收羅出大量的帖子,這裏我就很少說了,大體原理就是利用canvas裁剪圖像而後生成base64的圖像(canvas.toDataURL('image/jpeg'))。html
轉換Blob對象:接下來就是重點了,上傳圖片咱們比較傳統的作法就是將 canvas.toDataURL('image/jpeg') 傳到後臺,而後後臺再生成圖片傳到阿里雲。java
這樣就顯得比較繁瑣了,怎麼將 canvas.toDataURL('image/jpeg')直接傳到阿里雲?這就懵逼了。這裏不得不提到js的另外一個東西,Blob對象。android
file對象你們都不陌生了,那這個blob又是個什麼鬼呢?而實際上 file 對象只是 blob 對象的一個更具體的版本,blob 存儲着大量的二進制數據,而且 blob 的 size 和 type 屬性,都會被 file 對象所繼承。ios
因此, 在大多數狀況下,blob 對象和 file 對象能夠用在同一個地方,例如,可使用 FileReader 藉口從 blob 讀取數據,也可使用 URL.createObjectURL() 從 blob 建立一個新的 URL 對象。web
這裏我先用了canvas一個最簡單的辦法,建立blob。canvas.toBlob(callback,type,quality);咱們能夠直接把上傳圖片的方法寫到回調裏面,type:類型(圖片:‘image/jpeg’),quality:圖片質量(0-1).ajax
固然這麼高級的方法確定會涉及到兼容性問題。那咱們就回到blob對象的問題上來吧。在chrome早先版本和目前的android中,至少是andrid5.1以前的瀏覽器,包括微信瀏覽器等,都不支持blob的構造方法,須要使用BlobBuilder。chrome
var file=new Blob( [array.buffer], {type : "image/jpeg"});//會存在兼容性問題。這個blob的構造方法,在ios手機瀏覽器是支持的,可是在android手機瀏覽器不行。 json
桌面版的chrome瀏覽器解決了這個blob bug, 可是android手機仍是有這個問題,會返回一個type error,由於android瀏覽器不支持這個構造方法。你必須使用老版本的BlobBuilder API.canvas
解決辦法:
//首先要將dataURL轉換爲Uint8Array對象: function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return u8arr ; } // 接下來的事情就好辦多了,來一發兼容性blob寫法: try{ var jpeg = new Blob( [array], {type : "image/jpeg"}); } catch(e){ // TypeError old chrome and FF window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; if(e.name == 'TypeError' && window.BlobBuilder){ var bb = new BlobBuilder(); bb.append([array.buffer]); var jpeg = bb.getBlob("image/jpeg"); } else if(e.name == "InvalidStateError"){ // InvalidStateError (tested on FF13 WinXP) var jpeg = new Blob( [array.buffer], {type : "image/jpeg"}); } else{ // We're screwed, blob constructor unsupported entirely } }
上傳到阿里雲:
我查了一下阿里雲的web直傳的Js示例代碼,感受寫的有點複雜,仍是用ajax來解決這個問題吧,仍是先上代碼再來大體講一下這個問題吧。
Utils.ajax({ url: url1,//url1是先向後臺請求上傳阿里雲的一些參數接口 success: function (res) { if (res.errorCode == 0) { var ossData=new FormData(); ossData.append("OSSAccessKeyId",res.data.accessId);//Bucket 擁有者的Access Key Id。 ossData.append("policy",res.data.policy);//policy規定了請求的表單域的合法性 ossData.append("Signature",res.data.signature);//根據Access Key Secret和policy計算的簽名信息,OSS驗證該簽名信息從而驗證該Post請求的合法性 //---以上都是阿里的認證策略 ossData.append("key",res.data.dir+'/'+res.data.filename+'.jpg');//文件名字,可設置路徑 ossData.append("success_action_status",'200');// 讓服務端返回200,否則,默認會返回204 ossData.append('file', jpeg);//須要上傳的文件 file 這個 //接下來就是上傳阿里雲了的代碼了 //ossData.append("callback",callbackbody);//回調,非必選,能夠在policy中自定義 $.ajax({ url : res.data.host, //上傳阿里地址 data : ossData, processData: false,//默認true,設置爲 false,不須要進行序列化處理 cache: false,//設置爲false將不會從瀏覽器緩存中加載請求信息 async: false,//發送同步請求 contentType: false,//避免服務器不能正常解析文件---------具體的能夠查下這些參數的含義 //dataType: 'JSON',//不涉及跨域 寫json便可 type : 'post', success : function(callbackHost, request) {}, //callbackHost:success,request中就是 回調的一些信息,包括狀態碼什麼的 error : function() { alert("圖片上傳出錯!") } }); } } });
其實Utils.ajax和$.ajax都是同樣的,爲了區分我這樣寫的,Utils.ajax的請求是爲了獲得後臺的驗證。上傳阿里雲的一些證書啊,驗證碼什麼的。$.ajax就是上傳到阿里雲的請求。值得注意點是:
ossData.append('file', jpeg);//須要上傳的文件 file 這個jpeg就是咱們前面建立的blob。通常上傳到阿里雲成功後若是不返回任何東西,就不要寫入dataType了。
過程大概就是這樣,參考了幾我的的文章推薦給你們:https://www.cnblogs.com/flicat/p/5337054.html TypeArray、ArrayBuffer、Blob、File、DataURL、canvas的相互轉換
http://blog.csdn.net/u012811805/article/details/53885008 移動端UC瀏覽器不支持Blob的解決方案
https://www.cnblogs.com/mottled/p/6979536.html 阿里OSS ajax方式 web直傳