【uniapp】uniapp 使用uView框架 upload组件压缩图片

  • 【uniapp】uniapp 使用uView框架 upload组件压缩图片已关闭评论
  • 213 次浏览
  • A+
所属分类:Web前端
摘要

tips:如果本文对你有用,请爱心点个赞,提高排名,让这篇文章帮助更多的人。谢谢大家!比心❤~
如果解决不了,可以在文末加我微信,进群交流。


tips:如果本文对你有用,请爱心点个赞,提高排名,让这篇文章帮助更多的人。谢谢大家!比心❤~
如果解决不了,可以在文末加我微信,进群交流。

技术选型

背景

uView框架upload文件上传组件中没有h5端控制压缩的参数,超出文件大小也没有响应的提示,但是一般的上传文件场景,是需要控制文件大小的。

【uniapp】uniapp 使用uView框架 upload组件压缩图片


效果图

原图是4.8M,长宽为:3024*4032
【uniapp】uniapp 使用uView框架 upload组件压缩图片
【uniapp】uniapp 使用uView框架 upload组件压缩图片
【uniapp】uniapp 使用uView框架 upload组件压缩图片


封装图片压缩工具方法

  • 封装util.js
// 图片压缩 /**  * imgSrc 地址  * scale 压缩质量 0-1  * type 文件类型  */ export function compressImg(imgSrc, scale, type, callback) { 	// uni.$u.toast('压缩中') 	var img = new Image(); 	img.src = imgSrc; 	img.onload = function() { 		var that = this; 		var h = (img.height * scale).toFixed(0); // 默认按质量比例压缩 		var w = (img.width * scale).toFixed(0); 		var canvas = document.createElement('canvas'); 		var ctx = canvas.getContext('2d'); 		var width = document.createAttribute("width"); 		width.nodeValue = w; 		var height = document.createAttribute("height"); 		height.nodeValue = h; 		canvas.setAttributeNode(width); 		canvas.setAttributeNode(height); 		ctx.drawImage(that, 0, 0, w, h); 		var base64 = canvas.toDataURL('image/jpeg', scale); //压缩比例 		canvas = null; 		if (type == 'base64') { 			let data = { 				size: getBase64Size(base64), 				type: type, 				source: base64 			} 			callback(base64); 		} else { 			let blob = base64ToBlob(base64); 			// console.log('压缩后的大小', blob, blob.size, blob.type) 			const blobUrl = window.URL.createObjectURL(blob); //blob地址 			blob.source = blobUrl 			callback(blob); 		} 	} }  // base转Blob export function base64ToBlob(base64) {  	var arr = base64.split(','), 		mime = arr[0].match(/:(.*?);/)[1], 		bstr = atob(arr[1]), 		n = bstr.length, 		u8arr = new Uint8Array(n); 	while (n--) { 		u8arr[n] = bstr.charCodeAt(n); 	} 	return new Blob([u8arr], { 		type: mime 	}); }  // 获取base64的文件大小 export function getBase64Size(base64Str) { 	let size = 0; 	if (base64Str) { // 获取base64图片byte大小 		const equalIndex = base64Str.indexOf('='); // 获取=号下标 		if (equalIndex > 0) { 			const str = base64Str.substring(0, equalIndex); // 去除=号 			const strLength = str.length; 			const fileLength = strLength - (strLength / 8) * 2; // 真实的图片byte大小 			size = Math.floor(fileLength); // 向下取整 		} else { 			const strLength = base64Str.length; 			const fileLength = strLength - (strLength / 8) * 2; 			size = Math.floor(fileLength); // 向下取整 		} 	} else { 		size = null; 	} 	return size } 
index.vue中引入util.js,并在上传时使用
<template> 	<view class="components-wrap"> 		<u-form-item class='form-item-box' labelWidth='auto' :prop="column.name" borderBottom :ref="column.name"> 			<u-upload class="upload-wrap" width="102" :fileList="fileList" @afterRead="afterRead" @delete="deletePic" 				:sizeType="sizeType" @clickPreview="clickPreview" :name="column.name" multiple :disabled="disabled" 				:formkey="formkey"> 				<view class="material-add"> 					<u-button class='upload-btn' :disabled="disabled" text="上传图片"></u-button> 				</view> 			</u-upload> 		</u-form-item> 	</view> </template> <script> 	import { 		compressImg 	} from '@/utils/util.js' 	export default { 		data() { 			return { 				currentValue: false, 				fileList: [], 				sizeType: ['compressed'], 				fileMaxSize: 2 * 1024 * 1024, // 默认最大为2M 				fileMinSize: 50 * 1024 // 最小为50KB 			} 		}, 		methods: { 			clickPreview(url, lists, name) { 				console.log('预览图片', url, lists, name) 			}, 			getCompressionRatio(fileSize) { 				const multiple = (fileSize / this.fileMaxSize).toFixed(2) // 获取文件大小倍数,生成质量比 				let compressionRatio = 1 				if(multiple > 5) { 					compressionRatio = 0.5 				} else if (multiple > 4) { 					compressionRatio = 0.6 				} else if (multiple > 3) { 					compressionRatio = 0.7 				}else if (multiple > 2) { 					compressionRatio = 0.8 				} else if (multiple > 1) { 					compressionRatio = 0.9 				} else { 					compressionRatio = 2 				} 				return compressionRatio; 			}, 			// 新增图片 			async afterRead(event) { 				// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式 				let lists = [].concat(event.file) 				let fileListLen = this[`fileList`].length  				for (let index in lists) { 					const item = lists[index] 					const fileSize = item.size 					const fileName = item.name ?? '' 					if (fileSize > this.fileMaxSize) { 						const compressionRatio = this.getCompressionRatio(fileSize) 						if (compressionRatio > 1) { 							uni.$u.toast('文件' + fileName + '大于10M') 							return false 						} 						// 自动压缩图片' 						await this.compressImg(item, compressionRatio) 						if (item.size > this.fileMaxSize) { 							uni.$u.toast('文件' + fileName + '压缩后超出2M') 							return false 						} 					}  					if (item.size < this.fileMinSize) { 						uni.$u.toast('文件' + fileName + '不能小于50KB') 						return false 					}  					this[`fileList`].push({ 						...item, 						status: 'uploading', 						message: '上传中' 					}) 				} 				for (let i = 0; i < lists.length; i++) {  					const result = await this.uploadFilePromise(lists[i].url) 					// 垃圾回收 					window.URL.revokeObjectURL(lists[i].url) 					console.log('上传结果', result) 					let item = this[`fileList`][fileListLen] 					this[`fileList`].splice(fileListLen, 1, Object.assign(item, { 						status: 'success', 						message: '上传成功', 						url: result 					})) 					fileListLen++ 				} 			}, 			compressImg(source, compressionRatio) { 				return new Promise((resolve, reject) => { 					compressImg(source.url, compressionRatio, source.type, compressRes => { 						resolve(compressRes); 					}) 				}).then((res) => { 					source.size = res.size 					// window.URL.revokeObjectURL(source.url) // 删除被压缩的缓存文件,这里注意,如果是相册选择上传,可能会删除相册的图片 					source.url = res.source 					source.thumb = res.source 					return source 				}).catch(err => { 					console.log('图片压缩失败', err) 				}) 			}, 			uploadFilePromise(url) { 				let that = this 				return new Promise((resolve, reject) => { 					const uploadTask = uni.uploadFile({ 						url: uploadUrl, 						filePath: url, 						name: 'file', 						header: { 							"blade-auth": "Bearer xxxxxxxxxxxxx", 							"tenantCode": tenantCode 						}, 						success: (uploadFileRes) => { 							if (uploadFileRes.statusCode === that.Response.OK) { 								const data = JSON.parse(uploadFileRes.data) 								if (data.code === that.Response.OK) { 									console.log('form components upload uploadFilePromise onchange', 										uploadFileRes) 									let fileId = data.data[0].id; 									const sourceUrl = 'https://xxxxxxx/download-document/id/' + fileId; 									that.data.value.push({ 										id: fileId, 										name: data.data[0].name, 										source: sourceUrl 									}); 									// 添加图片数量 									that.data.count = that.fileList.length 									that.$emit('change', that.data, that.formkey) 									setTimeout(() => { 										resolve(sourceUrl) 									}, 500) 								} else { 									uni.showToast({ 										title: data.msg, 										icon: 'none', 										duration: that.ShowToast.DURATION 									}); 								} 							} else { 								console.log(uploadFileRes) 								uni.showToast({ 									title: '上传失败', 									icon: 'none', 									duration: that.ShowToast.DURATION 								}); 							} 						}, 						fail(error) { 							// reject(false) 							uni.$u.toast(error.errMsg) 							console.log('图片上传失败', error) 						} 					});  					// uploadTask.onProgressUpdate((res) => { 					// 	console.log('上传进度' + res.progress); 					// 	console.log('已经上传的数据长度' + res.totalBytesSent); 					// 	console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);  					// 	// 测试条件,取消上传任务。 					// 	if (res.progress > 50) { 					// 		uploadTask.abort(); 					// 	} 					// }); 				}) 			}, 		} 	}  <script/> 

有问题请添加个人微信:【mengyilingjian】,进群一起技术讨论。添加时请备注来意,谢谢!