小程序 上传图片并压缩

前段时间写过一次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)
		}
	}
})
遍历图片数据,进行压缩处理 ,记得要加 idthis
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)
			}
		})
	})
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值