当前位置: 首页 > article >正文

uniapp上传图片之前压缩处理

原理是使用canvas

压缩函数

compressImage(filePath) {  
				return new Promise((resolve, reject) => {  
					// 先获取图片信息,了解图片大小和尺寸
					uni.getImageInfo({  
						src: filePath,  
						success: (imageInfo) => {  
							// 创建临时文件路径
							const tempFilePath = filePath;  
							// 如果图片本身就小于1MB,并且尺寸不大,就不压缩了
							uni.getFileInfo({
								filePath: tempFilePath,
								success: (res) => {
									console.log("原始图片大小:", res.size / 1024, "KB");	
									// 如果文件已经足够小,直接返回原文件路径
									if (res.size < this.maxSize && imageInfo.width <= this.maxWidth) {
										resolve({
											path: tempFilePath,
											size: res.size
										});
										return;
									}
									// 计算缩放比例
									let ratio = 1;
									if (imageInfo.width > this.maxWidth) {
										ratio = this.maxWidth / imageInfo.width;
									}
									
									const newWidth = Math.floor(imageInfo.width * ratio);
									const newHeight = Math.floor(imageInfo.height * ratio);
									
									// 创建canvas绘制
									const canvas = document.createElement('canvas');
									canvas.width = newWidth;
									canvas.height = newHeight;
									const ctx = canvas.getContext('2d');
									
									// 创建图片对象
									const img = new Image();
									img.onload = () => {
										// 绘制图片到canvas
										ctx.clearRect(0, 0, newWidth, newHeight);
										ctx.drawImage(img, 0, 0, newWidth, newHeight);
										
										// 初始质量
										let quality = this.quality;
										let base64 = canvas.toDataURL('image/jpeg', quality);
										
										// 检查压缩后的大小
										let binaryData = atob(base64.split(',')[1]);
										let compressedSize = binaryData.length;
										
										console.log("首次压缩后大小:", compressedSize / 1024, "KB");
										
										// 如果压缩后仍然太大,则降低质量继续压缩
										let maxIterations = 5; // 最多尝试5次
										let currentIteration = 0;
										
										while (compressedSize > this.maxSize && currentIteration < maxIterations) {
											quality -= 0.1;
											if (quality < 0.2) quality = 0.2; // 最低质量限制
											
											base64 = canvas.toDataURL('image/jpeg', quality);
											binaryData = atob(base64.split(',')[1]);
											compressedSize = binaryData.length;
											
											console.log(`${currentIteration+1}次压缩, 质量:${quality}, 大小:${compressedSize / 1024}KB`);
											currentIteration++;
										}
										
										// 转换base64为Blob
										let binary = atob(base64.split(',')[1]);
										let array = [];
										for (let i = 0; i < binary.length; i++) {
											array.push(binary.charCodeAt(i));
										}
										let blob = new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
										
										// 创建文件对象
										let fileName = `compressed_${new Date().getTime()}.jpg`;
										let file = new File([blob], fileName, {type: 'image/jpeg'});
										
										resolve({
											file: file,
											size: compressedSize
										});
									};
									
									img.onerror = (e) => { 
										reject(e); 
									};
									
									// 设置图片来源


									img.src = tempFilePath;  
								},
								fail: (err) => {  
									reject(err);  
								}
							});
						},
						fail: (err) => {  
							reject(err);  
						}
					});
				});
			}

调用相机函数

	takePhoto() {
				// 直接调用相机拍照,不提供选择相册的选项
				uni.chooseImage({
					count: 1, // 限制只能选一张图片
					sourceType: ['camera'], // 只使用相机拍照
					sizeType: ['compressed', 'original'],
					success: (res) => {
						uni.showLoading({
							title: '图片上传中,请稍后...',
							mask: true
						});

						let fileItem = res.tempFiles[0];
						
						// 检查文件大小,如果超过1MB则压缩
						if (fileItem.size > this.maxSize) {
							console.log("图片需要压缩,原始大小:", fileItem.size / 1024, "KB");
							
							// 压缩图片
							this.compressImage(fileItem.path)
								.then(compressResult => {
									console.log("压缩后大小:", compressResult.size / 1024, "KB");
									let compressedFile = compressResult.file;
									// 上传压缩后的图片
									this.upload(compressedFile);
								})
								.catch(err => { 
									console.error("压缩图片失败:", err);

									uni.hideLoading(); 
									uni.showToast({ 
										title: '图片处理失败,请重试',

										icon: 'none', 
										duration: 2000 
									});
								});
						} else { 
							console.log("图片不需要压缩,大小:", fileItem.size / 1024, "KB");

							// 文件大小已经符合要求,直接上传

							let file = new File([fileItem], fileItem.name, { 
								type: fileItem.type 
							});
							//实际上传的函数(需要自己定义)
							this.upload(file);
						}
					},
					fail: (err) => {
						console.log('相机调用失败', err);
						uni.showToast({
							title: '相机调用失败',
							icon: 'none',
							duration: 2000
						});
					}
				})
			}

http://www.kler.cn/a/611913.html

相关文章:

  • 解构 HarmonyOS:技术神话背后的理性审视
  • 给聊天机器人装“短期记忆“:Flask版实现指南
  • 高级数据结构02AVL树
  • AI编程工具哪家强?对比Cusor、Copilot、Cline
  • C++算法深度解析:快速排序的实现、分析与优化
  • RoMA: 基于Mamba的遥感基础模型, 已开源, 首次验证mamba的scaling能力
  • 用数组遍历出来的页面,随节点创建的ref存储在数据仓库中,如果数据删除,页面相关节点也会删除,数据仓库中随节点创建的ref会不会也同时删除
  • STM32F103C8T6移植DMP解算MPU6050
  • Elasticsearch:使用 Azure AI 文档智能解析 PDF 文本和表格数据
  • linux---------进程概念(完)
  • 字节真题,问a,b,c指的地址是否相同?
  • SQL Server常见问题解析
  • 记录react和vue 属性传组件相关的事宜
  • 微软重磅发布 OmniParser V2.0:AI 视觉解析能力跃升,开启界面自动化新时代
  • 鸿蒙Flutter实战:20. Flutter集成高德地图,同层渲染
  • AG7220替代方案|ASL6328芯片设计|HDMI2.0 Retimer中继器方案
  • 核函数(机器学习深度学习)
  • win11+ubuntu双系统安装
  • 【解决】Linux命令报错:Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64
  • Python爬虫:Asyncpy 的详细使用和案例(高性能异步爬虫框架)