* @Date: 2016/11/17 0017 * @Time: 10:14 * @Author: lxbin * * Created with JetBrains WebStorm. */ /** * http://leonshi.com/2015/10/31/html5-canvas-image-compress-crop/ * http://jafeney.com/2016/08/11/20160811-image-upload/ * http://ilovetile.com/3506 */ /** * 讀取文件 * @param file 文件對象 * @return {Promise} */ function readFileAsync(file) { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = e => resolve(readFile.target.result) reader.onerror = e => reject(new Error('Could not read file')) reader.readAsDataURL(file) }) } /** * 加載圖片 * @param url 圖片地址 * @return {Promise} */ function loadImageAsync(url) { return new Promise((resolve, reject) => { const image = new Image() image.onload = () => resolve(image) image.onerror = () => reject(new Error('Could not load image at ' + url)) image.src = url }) } /** * base64的圖片dataUri轉Blob * @param dataURI * @return {*} */ function dataURItoBlob(dataURI) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this const byteString = atob(dataURI.split(',')[1]); // separate out the mime component const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] // write the bytes of the string to an ArrayBuffer const ab = new ArrayBuffer(byteString.length); const ia = new Uint8Array(ab); for (let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } // write the ArrayBuffer to a blob, and you're done return new Blob([ab], {type: mimeString}); // Old code // const bb = new BlobBuilder(); // bb.append(ab); // return bb.getBlob(mimeString); } /** * 圖片轉Blob * @param image 圖片對象 * @param quality 圖片質量(0到1之間) * @param scale 縮放比例(0到1之間) * @return {Promise} */ function imageToBlob(image, quality, scale) { return new Promise((resolve, reject) => { try { let canvas = document.createElement('canvas') canvas.width = image.naturalWidth * scale canvas.height = image.naturalHeight * scale while (canvas.width >= 3264 || canvas.height >= 2448) {//超過這個值base64沒法生成,在IOS上 canvas.width = canvas.naturalWidth * scale canvas.height = canvas.naturalHeight * scale } let ctx = canvas.getContext('2d').drawImage(image, 0, 0, canvas.width, canvas.height) //方式一:低版本兼容性差些 //canvas.toBlob(function (blob) { // console.group('[Leo]file compress to blob') // console.log('文件類型 => ' + image.type) // console.log('文件大小 => ' + (image.size / 1024 / 1024).toFixed(2) + 'M') // console.log('blob質量 => ' + quality) // console.log('blob大小 => ' + (blob.size / 1024 / 1024).toFixed(2) + 'M') // console.groupEnd() // resolve(blob) //}, 'image/jpeg', quality) //方式二: const base64 = canvas.toDataURL('image/jpeg', quality); const blob = dataURItoBlob(base64); blob.name = blob.filename = image.name console.group('[Leo]image compress to blob') console.log('文件類型 => ' + image.type) console.log('文件大小 => ' + (image.size / 1024 / 1024).toFixed(2) + 'M') console.log('blob質量 => ' + quality) console.log('blob大小 => ' + (blob.size / 1024 / 1024).toFixed(2) + 'M') console.groupEnd() resolve(blob); } catch (e) { reject(new Error("Image could not convert to blob :" + e)) } }) } /** * Ajax上傳 * @param uri 上傳的Action地址 * @param file 文件對象 * @return {Promise} */ function uploadFile(uri, file) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest() if (xhr.upload) { xhr.upload.addEventListener("progress", (e) => {// 處理上傳進度 if (e.lengthComputable) { let percent = (e.loaded / e.total * 100).toFixed(2) + '%' console.log("上傳中(" + percent + ")"); //TODO:反饋到DOM裏顯示 } else { console.log('unable to compute'); } }, false) } xhr.onreadystatechange = (e) => {// 文件上傳成功或是失敗 if (xhr.readyState === 4) { if (xhr.status === 200) { resolve(xhr.responseText)// 上傳成功 } else { reject(xhr.responseText)// 上傳出錯處理 } } } xhr.open("POST", uri, true)// 開始上傳 let form = new FormData() form.append("filedata", file, file.name) xhr.send(form) }) } /** * 上傳文件 * @param file 文件對象 * @param quality 圖片質量(0到1之間) * @param scale 縮放比例(0到1之間) */ export default async function fileUpload(file, quality, scale) { try { let fileUrl = await readFileAsync(file) let image = await loadImageAsync(fileUrl) image.name = file.name let blob = await imageToBlob(image, quality, scale) let upload = await uploadFile(blob) return upload } catch (e) { console.log('file upload failed') } }
http://leonshi.com/2015/10/31...
http://jafeney.com/2016/08/11...
http://ilovetile.com/3506html