一、UniApp简介
UniApp是一款基于Vue.js框架的跨平台开发工具,使用UniApp可以快速开发出同时适配多个平台的应用。UniApp可以将同一套代码快速打包为微信小程序、支付宝小程序、H5、App等多个平台的应用。此外,UniApp还提供了一些开箱即用的组件和插件,开发者可以快速构建出美观且功能丰富的应用。
二、图片处理与图片上传的设计
1. 图片处理的需求
在应用中,用户经常需要上传图片,但是上传的图片往往需要进行一些处理,例如压缩、裁剪、旋转等操作。因此,我们需要在应用中提供这些图片处理的功能。
一些关键点:
使用canvas对图片进行处理
通过设定画布的宽高,将图片进行裁剪、缩放等操作
使用drawImage()方法,将图片绘制在画布上
使用canvas.toDataURL()方法将绘制后的画布转换为base64格式的图片
2. 图片上传的需求
在应用中,用户上传的图片需要存放在服务器上,因此我们需要提供一个图片上传的功能。上传的图片需要满足一下要求:
支持上传多张图片
上传的图片需要进行压缩处理
上传的图片需要进行文件格式的验证
上传的图片需要支持断点续传
一些关键点:
使用uni.uploadFile()方法上传图片
使用Promise.all()方法,实现多张图片的上传
使用canvas.toBlob()方法,将处理后的图片转换成blob格式的文件
使用File对象,对文件的格式、大小进行验证
使用阿里云OSS对象存储实现文件上传
设置分片上传,实现断点续传
三、图片处理与图片上传的开发实践
1. 图片处理的开发
图片处理的开发比较简单,主要是通过canvas对图片进行处理。
// 获取图片画布和画布上下文
const canvas = uni.createCanvasContext('photo-canvas', this);
// 加载图片
canvas.drawImage(imgPath, 0, 0, imgWidth, imgHeight);
// 将画布转换为base64格式图片
canvas.toDataURL('png', 0.7, (res) => {
const base64Img = res.replace(/data:image\/(jpeg|png);base64,/, '');
// 将base64格式转为blob格式文件
this.compressImage(base64Img).then((file) => {
// 对文件进行上传
this.uploadFile(file);
})
});
2. 图片上传的开发
图片上传的开发相对较为复杂,需要考虑多个方面的问题。
首先,在上传图片前,需要对图片进行压缩处理,然后再进行上传。这里的压缩处理需要考虑到多个方面的问题,例如图片大小、图片质量、图片格式等。
// 压缩图片
compressImage(base64Img) {
const imgSize = base64Img.length / 1024 / 1024;
let maxSize = 1;
let maxQuality = 0.8;
let fileType = 'jpeg';
if (imgSize > 10) {
maxSize = 2;
} else if (imgSize <= 0.7) {
maxSize = 1;
} else {
maxSize = (imgSize / 3).toFixed(0);
maxSize = maxSize <= 1 ? 1 : maxSize;
}
const canvas = document.createElement('canvas');
const img = new Image();
return new Promise((resolve, reject) => {
img.src = base64Img;
img.onload = () => {
const imgWidth = img.width;
const imgHeight = img.height;
let cvsWidth, cvsHeight;
if (imgWidth > imgHeight) {
cvsWidth = maxSize * 1024;
cvsHeight = (imgHeight / imgWidth * maxSize * 1024).toFixed(0);
} else {
cvsHeight = maxSize * 1024;
cvsWidth = (imgWidth / imgHeight * maxSize * 1024).toFixed(0);
}
canvas.width = cvsWidth;
canvas.height = cvsHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, imgWidth, imgHeight, 0, 0, cvsWidth, cvsHeight);
canvas.toBlob((blob) => {
const compressFile = new File([blob], `test.${fileType}`, { type: `image/${fileType}` });
resolve(compressFile);
}, `image/${fileType}`, maxQuality);
}
})
}
其次,在图片上传时,需要考虑到图片上传的文件格式、文件大小的验证。这里我们可以通过File对象的一些方法,对文件进行验证。
// 验证文件大小是否合法
isValidFileSize(file) {
const fileSize = file.size / 1024 / 1024;
return fileSize <= this.fileMaxSize;
},
// 验证文件格式是否合法
isValidFileType(file) {
const fileType = file.type.split('/')[1];
return this.fileTypes.includes(fileType);
},
// 判断文件是否有效
isValidFile(file) {
return this.isValidFileSize(file) && this.isValidFileType(file);
}
最后,在文件上传时,我们可以利用阿里云OSS对象存储的SDK,实现文件的断点续传。
// 初始化OSS实例
initOSSClient() {
// ...
const config = {
aliyunUrl: process.env.UNI_ENV.aliyunUrl,
region: process.env.UNI_ENV.aliyun_os_region,
accessKeyId: process.env.UNI_ENV.aliyun_os_access_key_id,
accessKeySecret: process.env.UNI_ENV.aliyun_os_access_key_secret,
bucket: process.env.UNI_ENV.aliyun_os_bucket
};
return new OSS(config);
},
// 上传文件
uploadFile(file) {
if (this.isValidFile(file)) {
const client = this.initOSSClient();
const expire = new Date().getTime() + (this.expireMinute * 60 * 1000);
const options = {
progress: (percentage) => { // 上传进度
this.uploadProgress = (percentage * 100).toFixed(0);
},
meta: { // 自定义元数据
fileType: file.type,
fileName: file.name,
fileTimeStamp: new Date().getTime(),
expire: expire,
from: this.from
}
};
client.multipartUpload(this.genUploadFileName(), file, options).then((data) => {
// 上传成功
}).catch((err) => {
// 上传失败
});
}
}
四、总结
图片处理与图片上传是一个常见的开发需求,在UniApp中的实现主要是利用canvas进行图片处理,在使用uni.uploadFile()方法上传图片时,通过Promise.all()方法实现多张图片的上传,使用阿里云OSS对象存储实现文件上传。