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, //默认9sizeType:['compressed'],success: (chooseImageRes) => {const tempFilePaths = chooseImageRes.tempFilePaths;const filePath = tempFilePaths[0];// 获取图片文件大小uni.getFileInfo({filePath: filePath,success: (fileInfo) => {const fileSize = fileInfo.size; // 图片文件大小,单位为B// 判断图片大小是否超过200KBif (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(); // 隐藏 loadingif (res.statusCode === 200) {console.log('上传成功:', res.data);const responseData = JSON.parse(res.data); // 解析返回的数据console.log(responseData,'responseData')// 处理上传成功后的逻辑if(responseData.code==200){this.contractImage1 = responseData.datauni.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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/707366.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity中字符串拼接0GC方案

本文主要分析C#字符串拼接产生GC的原因&#xff0c;以及介绍名为ZString的库&#xff0c;它可以将字符串生成的内存分配为零。 在C#中&#xff0c;字符串拼接通常有三种方式&#xff1a; 直接使用号连接&#xff1b;string.format;使用StringBuilder&#xff1b; 下面分别细…

新版极狐gitlab安装+配置详细版

这里安装的服务器环境是centos7.9系统&#xff0c;安装极狐版本16.9。 极狐地址&#xff1a;https://gitlab.cn/install/ 1. 安装和配置所需的依赖 在 CentOS 7 上&#xff0c;下面的命令会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤&#xff0c;如果您…

Docker部署Portainer图形化管理工具

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

物业智能水电抄表管理系统

物业智能水电抄表管理系统是物业管理行业的关键技术之一&#xff0c;其结合了智能化、远程监控和数据分析等功能&#xff0c;为物业管理公司和业主提供了高效、精准的水电抄表管理解决方案。该系统具有多项优势&#xff0c;能够提升物业管理效率&#xff0c;降低成本&#xff0…

第五节:Vben Admin权限-前端控制方式

系列文章目录 第一节:Vben Admin介绍和初次运行 第二节:Vben Admin 登录逻辑梳理和对接后端准备 第三节:Vben Admin登录对接后端login接口 第四节:Vben Admin登录对接后端getUserInfo接口 第五节:Vben Admin权限-前端控制方式 文章目录 系列文章目录前言一、Vben Admin权…

py32 link,让PY32单片机开发更容易上手。

py32 link支持PY32系列单片机的调试和烧录&#xff0c;⽀持Keil、IAR等多种开发环境&#xff0c;开发简单易上手。PY32 link使用Type-C接⼝供电&#xff0c;搭载了MH32F103A芯片 LQFP64封装&#xff0c;MH32F103A有着216MHz主频和256KB flash&#xff0c;96KB RAM大资源&#x…

集合进阶(三)——List

List集合的特有方法 List集合因为支持索引&#xff0c;所以多了很多与索引相关的方法&#xff0c;当然&#xff0c;List也继承了Collection的功能 方法名说明void add(int index, E element)在此集合中的指定位置插入指定的元素E remove(int index)删除指定索引处的元素…

RxJava 操作符的原理

今天再一次看Rxjava的几个操作符时发现对于操作符到底做了什么事不是很清楚&#xff0c;使用just&#xff0c;create等操作符创建一个Observable&#xff0c;和使用filter、map等操作符对Observable发送的数据进行转换有什么区别和联系&#xff1f;filter和map这样的操作符最终…

【Python】Code2flow学习笔记

1 Code2flow介绍 Code2flow是一个代码可视化工具库&#xff0c;旨在帮助开发人员更好地理解和分析代码&#xff1a; 可以将Python代码转换为流程图&#xff0c;以直观的方式展示代码的执行流程和逻辑结构。具有简单易用、高度可定制化和美观的特点&#xff0c;适用于各种代码…

人工智能与网络安全

目录 概述 人工智能在网络安全中的应用 威胁检测 自动化响应

Groovy(第九节) Groovy 之单元测试

JUnit 利用 Java 对 Song 类进行单元测试 默认情况下 Groovy 编译的类属性是私有的,所以不能直接在 Java 中访问它们,必须像下面这样使用 setter: 编写这个测试用例余下的代码就是小菜一碟了。测试用例很好地演示了这样一点:用 Groovy 所做的一切都可以轻易地在 Java 程序…

MySQL中的 left join 使用场景介绍及注意事项

left join 1. 使用场景 在MySQL中多表联查有多种方式&#xff0c;使用left join 一般是想保留某张表的数据完整&#xff0c;也就是说在查询结果中指定表行数不会随查询条件改变。 2. 语法 select &#xff08;所需要的列&#xff09; from 表1 left join 表2 on 表1.关联…

算法--动态规划(线性DP、区间DP)

这里写目录标题 tip数组下标从0开始还是从1开始 线性DP数学三角形介绍算法思想例题代码 最长上升子序列介绍算法思想例题代码 最长公共子序列介绍算法思想例题代码 编辑距离介绍例题代码 区间DP问题石子合并介绍算法思想例题代码 tip 数组下标从0开始还是从1开始 如果代码中涉…

Opencv实战(3)详解霍夫变换

霍夫变换 Opencv实战系列指路前文&#xff1a; Opencv(1)读取与图像操作 Opencv(2)绘图与图像操作 文章目录 霍夫变换1.霍夫线变换1.1 原理1.2 HoughLines() 2.霍夫圆变换2.1 原理2.2 HoughCircles() 最基本的霍夫变换是从黑白图像中检测直线(线段) 霍夫变换(Hough Transform…

【vue】什么是虚拟Dom,怎么实现虚拟DOM,虚拟DOM一定更快吗

什么是虚拟Dom 虚拟 DOM 基于虚拟节点 VNode&#xff0c;VNode 本质上是一个对象&#xff0c;VDOM 就是VNode 组成的 废话&#xff0c;js 中所有的东西都是对象 虚拟DOM 为什么快&#xff0c;做了哪些优化 批量更新 多个DOM合并更新减少浏览器的重排和重绘局部更新 通过新VDO…

【PHP设计模式08】装饰模式

【装饰模式】 装饰模式,又称装饰器模式 或 装饰者模式 或 油漆工模式,通过创建一个“装饰对象”,在不改变原有类和使用继承的情况下,动态地扩展一个对象的功能,比直接生成子类继承更加灵活,可以通过多个不同的具体装饰类,创建多个不同的行为组合。 结构: 抽象构件…

Spring中的ApplicationContext.publishEvent

简单理解 其实就是监听处理。比如找工作平台上&#xff0c;雇主 employer 发布自己的雇佣条件&#xff0c;目的是平台中有符合条件的求职者时&#xff0c;及时向雇主推荐。求职者发布简历&#xff0c;当平台发现某个求职者比较符合条件&#xff0c;就触发被动&#xff0c;推荐…

selenium元素等待及滚动条滚动

selenium三大等待&#xff0c;sleep&#xff08;强制&#xff09;、implicitlyWait&#xff08;隐式等待&#xff09;、WebDriverWait&#xff08;显式等待&#xff09;&#xff0c;主要记一下最后面的WebDriverWait。 WebDriverWait是三大等待中最常用也是最好用的一种等待方…

docker 容器修改端口和目录映射

一、容器修改端口映射 一般在运行容器时&#xff0c;我们都会通过参数 -p&#xff08;使用大写的-P参数则会随机选择宿主机的一个端口进行映射&#xff09;来指定宿主机和容器端口的映射&#xff0c;例如 docker run -it -d --name [container-name] -p 8088:80 [image-name]…

vue3的echarts从后端获取数据,用于绘制图表

场景需求&#xff1a;后端采用flask通过pymysql从数据库获取数据&#xff0c;并返回给前端。前端vue3利用axios获取数据并运用到echarts绘制图表。 第一步&#xff0c;vue中引入echarts 首先vue下载echarts npm install echarts 然后在main.js文件写如下代码 import {create…