uniapp 上传压缩图片 兼容h5和小程序的方法

项目是用uniapp开发的,当时只是做App端,后来项目扩展到H5端, uniapp框架可以跨平台所以移动端和H5使用的是一套代码

上传头像的时候要求图片的大小在2MB一下,所以要压缩图片,App端当时使用的是uni.compressImage(OBJECT)压缩的(详情见:https://uniapp.dcloud.net.cn/api/media/image.html#compressimage 但是H5不兼容;

先搞定H5的压缩吧!网上一搜一大把

/** 
 * H5压缩 二分查找算法来找到一个合适的图像质量系数,使得压缩后的图片文件大小接近于目标大小
 * @param {Object} imgSrc 图片url 
 * @param {Object} callback 回调设置返回值 
 * */
 export function compressH5(fileItem, targetSizeKB, initialQuality = 1.0) { const maxQuality = 1.0;
     const minQuality = 0.0;
     const tolerance = 0.01; // 根据需要调整公差
     return new Promise((resolve, reject) => { const binarySearch = (min, max) => { const midQuality = (min + max) / 2;
 
             const reader = new FileReader();
             reader.readAsDataURL(fileItem);
             reader.onload = function () { const img = new Image();
                 img.src = this.result;
                 img.onload = function () { const canvas = document.createElement('canvas');
                     const ctx = canvas.getContext('2d');
 
                     canvas.width = img.width;
                     canvas.height = img.height;
 
                     ctx.clearRect(0, 0, canvas.width, canvas.height);
                     ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
 
                     // 使用异步的 toBlob 方法
                     canvas.toBlob(async (blob) => { const fileSizeKB = blob.size / 1024;
 
                         if (Math.abs(fileSizeKB - targetSizeKB) < tolerance || max - min < tolerance) { // 当前质量足够接近目标大小,使用当前质量解析
                             resolve(URL.createObjectURL(blob));
                         } else if (fileSizeKB > targetSizeKB) { // 如果文件大小太大,降低质量,继续二分查找
                             binarySearch(min, midQuality);
                         } else { // 如果文件大小太小,增加质量,继续二分查找
                             binarySearch(midQuality, max);
                         }
                     }, 'image/jpeg', midQuality);
                 };
             };
             reader.onerror = function (error) { reject(error);
             };
         };
 
         // 开始二分查找
         binarySearch(minQuality, maxQuality);
     });
 }

调用方法

chooseImg1() { uni.chooseImage({count: 1, //默认9
					sizeType:['compressed'],
			        success: (chooseImageRes) => { const tempFilePaths = chooseImageRes.tempFilePaths;
			            const filePath = tempFilePaths[0];
			            // 获取图片文件大小
			            uni.getFileInfo({ filePath: filePath,
			                success: (fileInfo) => { const fileSize = fileInfo.size; // 图片文件大小,单位为B
			                    // 判断图片大小是否超过200KB
			                    if (fileSize > 200 * 1024) {//#ifdef H5
									 //h5压缩图片
																		 const targetSizeKB = 150; // 设置目标文件大小,单位为KB,根据需求调整
compressH5(chooseImageRes.tempFiles[0],targetSizeKB).then(file => {console.log('file 222 = ', file)
											this.uploadCompressedImage(file);
											}).catch(err => {console.log('catch', err)
									 })
									//#endif
									//#ifdef APP-PLUS || MP-WEIXIN
			                        // 如果超过200KB,进行压缩
			                        uni.compressImage({ src: filePath,
			                            quality: 10, // 设置压缩质量(0-100)- 根据需求进行调整
			                            success: (compressRes) => { // 压缩成功后的逻辑
			                                this.uploadCompressedImage(compressRes.tempFilePath);
			                            },
			                            fail: (err) => { console.error('压缩图片失败:', err);
			                                uni.showToast({ title: '压缩图片失败,请重试',
			                                    icon: 'none'
			                                });
			                            }
			                        });
									//#endif
			                    } else { // 如果未超过200KB,直接上传原图
			                        this.uploadCompressedImage(filePath);
			                    }
			                },
			                fail: (err) => { console.error('获取文件信息失败:', err);
			                    uni.showToast({ title: '获取文件信息失败,请重试',
			                        icon: 'none'
			                    });
			                }
			            });
			        },
			        fail: (err) => { console.error('选择图片失败:', err);
			            uni.showToast({ title: '选择图片失败,请重试',
			                icon: 'none'
			            });
			        }
			    });
			},
uploadCompressedImage(filePath) { uni.uploadFile({ url: `${this.$VUE_APP_API_URL}/common/image/image/upload/faceImg`,
						filePath: filePath,
			            name: 'file',
			            header: { 'Authorization': uni.getStorageSync('X-Token'), // 修改为你的访问令牌
			            },
						success: (res) => {uni.hideLoading(); // 隐藏 loading
							if (res.statusCode === 200) {console.log('上传成功:', res.data);
								const responseData = JSON.parse(res.data); // 解析返回的数据
								console.log(responseData,'responseData')
								// 处理上传成功后的逻辑
								if(responseData.code==200){this.contractImage1 = responseData.data
									uni.setStorageSync('faceUrl',this.contractImage1)
								}else{uni.$u.toast(responseData.msg);
								}
							} else {console.error('上传失败', res.statusCode);
								uni.showToast({title: res.msg, // 自定义错误信息
									icon: 'none'
								});
							}
						},
			            fail: (err) => { console.error('上传失败:', err);
			                uni.showToast({ title: '上传失败,请重试',
			                    icon: 'none'
			                });
			            }
			        });
			    },

即能兼容h5也能兼容微信小程序和各个app

微信小程序图片压缩再次用二分查找压缩质量

// 压缩图片
export function compressImage(filePath, quality, successCallback, errorCallback) { uni.compressImage({ src: filePath,
        quality: quality,
        success: (res) => { successCallback(res.tempFilePath);
        },
        fail: (err) => { errorCallback(err);
        }
    });
}
// 二分查找压缩质量
export function binarySearchCompress(filePath, targetSize, low, high, successCallback, errorCallback) { if (low > high) { errorCallback("无法达到目标大小");
        return;
    }
    const mid = Math.floor((low + high) / 2);
    compressImage(filePath, mid, (tempFilePath) => { uni.getFileInfo({ filePath: tempFilePath,
            success: (res) => { const currentSize = res.size;
                if (currentSize <= targetSize) { successCallback(tempFilePath);
                } else { // 递归调整压缩质量
                    binarySearchCompress(filePath, targetSize, low, mid - 1, successCallback, errorCallback);
                }
            },
            fail: (err) => { errorCallback(err);
            }
        });
    }, (err) => { errorCallback(err);
    });
}

vue文件引用

//#ifdef APP-PLUS || MP-WEIXIN
			                        // 如果超过200KB,进行压缩
												
									  const tempFilePath = chooseImageRes.tempFilePaths[0];
									  const targetSizeKB = 200;
									  // 将目标大小转换为字节数
									  const targetSize = targetSizeKB * 1024;
									  // 初始压缩质量范围
									  const lowQuality = 1;
									  const highQuality = 100;
									  binarySearchCompress(tempFilePath, targetSize, lowQuality, highQuality, (compressedFilePath) => { console.log("压缩成功,压缩后图片路径:", compressedFilePath);
										     this.uploadCompressedImage(compressedFilePath);
										  
									  }, (err) => { console.error("压缩失败:", err);
									  })
									//#endif