Vue 图片压缩并上传至服务器
本文主要講解基于 Vue + Vant ,實(shí)現(xiàn)移動端圖片選擇,并用 Canvas 壓縮圖片,最后上傳至服務(wù)器。還會封裝一個工具類,方便直接調(diào)用。
一、工具類封裝
廢話不多說先上代碼,封裝一個 CompressImageUtils?工具類:
/*** 圖片壓縮工具類* 最大高度和最大寬度都為 500,如果超出大小將等比例縮放。** 注意可能出現(xiàn)壓縮后比原圖更大的情況,在調(diào)用的地方自己判斷大小并決定上傳壓縮前或壓縮后的圖到服務(wù)器。*/// 將base64轉(zhuǎn)換為blob export function convertBase64UrlToBlob(urlData) {let arr = urlData.split(',')let mime = arr[0].match(/:(.*?);/)[1]let bstr = atob(arr[1])let n = bstr.lengthlet u8arr = new Uint8Array(n)while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new Blob([u8arr], {type: mime}) }// 壓縮圖片 export function compressImage(path) {//最大高度const maxHeight = 500;//最大寬度const maxWidth = 500;return new Promise((resolve, reject) => {let img = new Image();img.src = path;img.onload = function () {const originHeight = img.height;const originWidth = img.width;let compressedWidth = img.height;let compressedHeight = img.width;if ((originWidth > maxWidth) && (originHeight > maxHeight)) {// 更寬更高,if ((originHeight / originWidth) > (maxHeight / maxWidth)) {// 更加嚴(yán)重的高窄型,確定最大高,壓縮寬度compressedHeight = maxHeightcompressedWidth = maxHeight * (originWidth / originHeight)} else {//更加嚴(yán)重的矮寬型, 確定最大寬,壓縮高度compressedWidth = maxWidthcompressedHeight = maxWidth * (originHeight / originWidth)}} else if (originWidth > maxWidth && originHeight <= maxHeight) {// 更寬,但比較矮,以maxWidth作為基準(zhǔn)compressedWidth = maxWidthcompressedHeight = maxWidth * (originHeight / originWidth)} else if (originWidth <= maxWidth && originHeight > maxHeight) {// 比較窄,但很高,取maxHight為基準(zhǔn)compressedHeight = maxHeightcompressedWidth = maxHeight * (originWidth / originHeight)} else {// 符合寬高限制,不做壓縮}// 生成canvaslet canvas = document.createElement('canvas');let context = canvas.getContext('2d');canvas.height = compressedHeight;canvas.width = compressedWidth;context.clearRect(0, 0, compressedWidth, compressedHeight);context.drawImage(img, 0, 0, compressedWidth, compressedHeight);let base64 = canvas.toDataURL('image/*', 0.8);let blob = convertBase64UrlToBlob(base64);// 回調(diào)函數(shù)返回blob的值。也可根據(jù)自己的需求返回base64的值resolve(blob)}}) }定義的最大寬度和最大高度均為 500,如果圖片的寬高至少有一個超出了 500,都會被?**等比例?**壓縮,不用擔(dān)心變形。可以根據(jù)自己項(xiàng)目需要改變maxWidth?和?maxHeight?。
這里直接把壓縮的最大高度和最大寬度寫死為 500 了,沒有在調(diào)用時傳。因?yàn)橐粋€項(xiàng)目壓縮的邏輯和大小一般都一致的,沒必要在每次調(diào)用的時候傳。當(dāng)然如果想寫的靈活一點(diǎn),可以在 compressImage?方法里再把 maxWidth?、 maxHeight?和壓縮質(zhì)量傳上。
compressImage 方法返回的是 blob 值,根據(jù)服務(wù)端接口需要可以改為返回 base64,只需將 resolve(blob)?改為 resolve(base64)?即可。
注意一點(diǎn),對于有些寬高沒到 500,且分辨率很小的圖片,壓縮之后可能比之前還大。猜測可能是 canvas?生成的圖片分辨率要比原來高一些,所以最終的圖片比壓縮前更大。可以在調(diào)用的地方加個判斷,如果壓縮完的大小比原圖小,就上傳壓縮后的圖片;如果如果壓縮完的大小比原圖大,就上傳原圖。
二、如何使用
將 CompressImageUtils?引入到目標(biāo)文件,然后調(diào)用?compressImage?方法,即可在回調(diào)里獲得壓縮后的結(jié)果。注意?compressImage 方法返回的是 Promise。
省略其他無關(guān)代碼,只保留跟壓縮圖片和上傳相關(guān)的:
在返回結(jié)果中加了層判斷,壓縮后比原來更大,則將原圖上傳;壓縮后比原來小,上傳壓縮后的。解決壓縮后比原圖更大的情況。
this.$api.uploadImage(params)?是調(diào)用封裝的 api 方法,如下:
三、使用效果
先上傳一個非常大的,尺寸為 6016?×?4016,16.8M 的大圖,看輸出日志,壓縮后大小僅為 260k 左右。此時判斷壓縮后比壓縮前小,上傳壓縮圖到服務(wù)器。
再看個尺寸 300?×?300,12k 的小圖,壓縮前大小是 11252,壓縮后大小是 93656,大了很多。此時判斷壓縮后比壓縮前更大,上傳的是原圖。
總結(jié):這個工具類對大圖的壓縮效果很明顯,不管多大的圖,壓縮之后基本不會超過 300k。但對某些小圖可能出現(xiàn)壓縮完反而更大的情況。在調(diào)用的地方加層壓縮后和壓縮前大小的比較判斷,會完美解決這個問題。
當(dāng)然也可以在工具類內(nèi)部判斷,但個人覺得跟業(yè)務(wù)邏輯相關(guān)的代碼還是不要放在公用的工具類比較好。
總結(jié)
以上是生活随笔為你收集整理的Vue 图片压缩并上传至服务器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【读书笔记】之《月亮与六便士》
- 下一篇: redis数据备份