小程序 上传图片并压缩

    技术2022-07-10  158

    前段时间写过一次h5利用canvas压缩图片的方法,本以为小程序压缩也大同小异,结果不慎掉入坑中爬了好久,这里以uniapp 为例总结一下: canvas压缩多张图片(一) canvas压缩多张图片(二)

    上传图片 chooseImage

    这里要和h5利用input 上传不同,这里需要利用chooseImage上传图片

    uni.chooseImage({ count: 9, sourceType: ['album','camera'], sizeType: ['compressed'], success(res) { if(res.errMsg =='chooseImage:ok'){ that.urlTobase64Fn(res.tempFilePaths) } } })
    遍历图片数据,进行压缩处理 ,记得要加 id 和 this
    async urlTobase64Fn (arr){ for(let i=0;i<arr.length;i++){ //这里很重要 canvasId this let base64=await urlTobase64(arr[i],"canvasId",this); this.imgArr.push(base64) } }, <canvas id="canvasId" class="canvasId" canvas-id="canvasId" ></canvas> .canvasId{ position: absolute; top:-9999rpx; left: -9999rpx; z-index: 0; width: 690rpx; height: 690rpx; }

    对URL进行处理 urlTobase64 (这是自定义的方法)

    //base64 urlTobase64 = async (fileObj,_this)=>{ //截取文件类型,转换为base64 let type=fileObj.type || fileObj.path.substring(fileObj.path.lastIndexOf('.')+1); let base64 = await getFileSystemManagerFn({ path:fileObj.path, type }); base64 = base64.replace(/[\r\n]/g, ""); // console.log(base64,'base') //如果是视频 if(type =='mp4'){ console.log('是视频,直接输出base64') //如果上传不是获取视频,则返回空 return fileObj.fileType =='video'?base64 : '' } let imgSize = await getBase64SizeFn(base64); console.log(imgSize,'是图片,判断图片大小'); //自定义图片大小限制、默认为 200kb fileObj.limitNum = fileObj.limitNum || 1024 *0.2; if(imgSize >fileObj.limitNum && type !='gif'){ console.log(imgSize,'需要压缩') let imgInfo = await getImageInfoFn (fileObj.path); fileObj.canvasId = fileObj.canvasId || 'canvasId'; return await convertImgToBase64Fn({ ...fileObj, oldH : imgInfo.height, oldW : imgInfo.width, // path : base64, //用微信临时地址,不要用base64 这里很重要,千万不要打开 type : imgInfo.type },_this); } else { console.log(imgSize,'可以直接使用'); //在限制大小之下,直接返回base64值 return base64 } }, //canvas 压缩 convertImgToBase64Fn = async (obj,_this) =>{ obj.minW = obj.minW || 750, obj.minH = obj.minH || 1334; obj.num = obj.num || 1; var cvsw,cvsh; //横向 图 if(obj.oldW > obj.oldH){ cvsh = obj.oldH > obj.minH ? obj.minH : obj.oldH; cvsw = cvsh / obj.oldH * obj.oldW } //纵向图 else if(obj.oldW < obj.oldH){ cvsw = obj.oldW > obj.minW ? obj.minW : obj.oldW; cvsh = cvsw / obj.oldW * obj.oldH } //正方形 else if(obj.oldW == obj.oldH && obj.oldW > obj.minW){ cvsw = obj.minW; cvsh = obj.minH; } //不必重置宽高 else { cvsw = obj.oldW; cvsh = obj.oldH; } //对宽高 进行取整 cvsw = parseInt(cvsw); cvsh = parseInt(cvsh); //设置canvas画布大小 console.log(cvsw,cvsh,'设置canvas画布大小'); _this.windowInfo ={ width:cvsw, height:cvsh } let dataURL = await canvasToTempFilePathFn({...obj,cvsw,cvsh},_this); console.log(dataURL.substring(0,50),'输出压缩后最终地址') return dataURL; }, //将base64 判断大小 getBase64SizeFn =(base64url) =>{ //获取base64图片大小,返回KB数字 var strLength =base64url.length; var fileLength = parseInt(strLength - (strLength / 8) * 2); // 由字节转换为KB var size = ""; size = (fileLength / 1024).toFixed(2); return parseInt(size) *1; }, //获取图片信息 getImageInfoFn = (url)=>{ console.log(url,'去获取图片信息') return new Promise((resolve)=>{ wx.getImageInfo({ src: url, success: (res)=> { console.log(res.path,'图片信息') resolve(res) } }); }) }, //绘制画布,并返回图片地址 canvasToTempFilePathFn =(obj,_this)=>{ return new Promise((resolve,reject)=>{ const ctx = uni.createCanvasContext(obj.canvasId,_this); console.log(obj.num,obj.type,'压缩开始') ctx.drawImage(obj.path, 0, 0, obj.cvsw, obj.cvsh); ctx.draw(false, setTimeout(()=>{ uni.canvasToTempFilePath({ canvasId :obj.canvasId, fileType :obj.type, quality :obj.num, width :obj.cvsw, height :obj.cvsh, destWidth :obj.cvsw, destHeight :obj.cvsh, success: async (res1) =>{ //转换为base64 console.log('去将压缩后的地址转base64') let base64 = await getFileSystemManagerFn({ path:res1.tempFilePath, type:obj.type }); base64 = base64.replace(/[\r\n]/g, ""); console.log('去后去压缩后的base64大小') let imgSize = getBase64SizeFn(base64); if( imgSize >= obj.limitNum && obj.num >0.6){ console.log(imgSize,'图片过大,继续压缩') obj.num = obj.num - 0.2 ; obj.num = obj.num.toFixed(2) *1; //重置图片格式 if(obj.type =='png' || obj.type =='PNG'){ obj.type ='png' } else{ obj.type ='jpg' } //继续压缩 canvasToTempFilePathFn({...obj},_this).then((res2)=>{ resolve(res2) }); } else{ console.log(imgSize,'最终压缩后图片大小') resolve(base64) } }, fail: function (e) { console.log('失败') reject(e) } },_this) },200)); }) }, //将图片转 base64 getFileSystemManagerFn =(obj)=>{ // console.log(obj.path,'图片地址') return new Promise(async (resolve,reject)=>{ let path = obj.path; //微信图片,先去下载 if(path.indexOf('https://wx.qlogo.cn') >=0){ path = await downloadFileFn(path); } // console.log(path,'地址') wx.getFileSystemManager().readFile({ filePath:path, encoding:'base64', success: async res=>{ console.log(obj.type,'图片类型') let base64=`data:image/${obj.type};base64,${res.data}`; resolve(base64) } }); }) }, //将图片下载到本地 downloadFileFn =(url)=>{ return new Promise ((resolve,reject)=>{ wx.downloadFile({ url, success(res) { resolve(res.tempFilePath) }, fail:err=>{ reject(err) } }) }) }
    Processed: 0.064, SQL: 9