uniapp 微信小程序开发 图片上传压缩
- 安卓上传图片并压缩
- 思路
- 全部代码
安卓上传图片并压缩
由于后端接口对图片的大小有限制,所以在上传图片是需要压缩处理:
uni.chooseImage({
count: 1, // 头像只上传1张
sizeType: ['compressed'], //指定压缩图,
success: async (chooseImageRes) => {
} catch (e) {
console.log(e)
}
},
fail(err) {
console.log(err)
}
})
但是最后真机测试后发现,iOS会自动压缩上传,安卓机并不会(测试了OPPO、荣耀、小米),一个5M的图片,iOS上传后会自动压缩为102k,安卓完全不会压缩。所以需要根据机型来判断是否需要需要压缩。
思路
条件编译
如果是微信小程序,判断机型,如果为安卓则压缩,使用canvas压缩(这里应该也可以使用自带的uni.compressImage,但是由于我们项目后端对类型有判断,而compressImage返回的图片路径是无后缀名的,所以弃用了);
如果是app端则使用5+(plus.zip.compressImage);
全部代码
const common = {
/**
* 清除文件
*/
clearFile() {
return new Promise((resolve) => {
// 把文件删除后再写进,防止超过最大范围而无法写入
const fsm = wx.getFileSystemManager(); //文件管理器
fsm.readdir({ // 获取文件列表
dirPath: wx.env.USER_DATA_PATH, // 当时写入的文件夹
success(res) {
console.log(res)
res.files.forEach((el) => { // 遍历文件列表里的数据
// 删除存储的垃圾数据
fsm.unlink({
filePath: `${wx.env.USER_DATA_PATH}/${el}`, // 这里注意。文件夹也要加上,如果直接文件名的话会无法找到这个文件
fail(e) {
console.log('readdir文件删除失败:', e)
}
});
})
resolve()
}
})
})
},
/**
* 获取图片信息
* @param {string} imgObj 图片对象path
* @param {function} fn 回调函数
* @returns {ojbect} cbParams
* {
* height: 722,
* width: 1366,
* type: 'png',
* path: '',
* orientation: 'up',
* errMsg: ''
* }
*/
getImageObject(src, fn) {
uni.getImageInfo({
src: src,
success(res) {
console.log(res)
fn(res)
}
})
},
/**
* 压缩图片
* @param {object} img 图片
* @param {function} fn 回调函数
*/
compressImg(img, fn, fail) {
//#ifdef MP-WEIXIN
//获取canvas
const selectorQuery = uni.createSelectorQuery()
selectorQuery.select('#canvas')
.fields({
//返回节点信息,文档中说只有当canvas的type为weldg时才能生效,但是经过测试是可以用的
node: true,
size: true
})
.exec(res => {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
canvas.height = img.height
canvas.width = img.width
let seal = canvas.createImage();
seal.src = img.path;
seal.onload = () => {
//画图
ctx.drawImage(seal, 0, 0, img.width, img.height)
//压缩
const url = canvas.toDataURL('image/jpeg',0.5)
//清除历史文件,否则可能会导致无法写入
this.clearFile().then(() => {
const FILE_BASE_NAME = 'tmp_base64src';
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(url) || [];
if (!format) {
fail && fail({errMsg: 'ERROR_BASE64SRC_PARSE'});
return;
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
//将base64转为文件流,输出临时文件上传
const buffer = uni.base64ToArrayBuffer(bodyData);
console.log('filePath',filePath)
const fsm = wx.getFileSystemManager();
fsm.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
fn(filePath)
},
fail(err) {
fail && fail(err)
}
})
})
}
})
//#endif
//#ifndef MP-WEIXIN
//5+自带的图片压缩
plus.zip.compressImage({
src: img.path,
quality: 0.1,
width: 50,
height: 50
}, (res) => {
console.log(res)
fn(res.target)
}, (err) => {
console.log(err)
fail && fail(err)
});
//#endif
}
}
页面使用示例:
//template
<canvas canvas-id="canvas" id="canvas" type="2d" ></canvas>
//methods
/**
* 上传头像触点
*/
uploadIcon() {
let _this = this;
uni.chooseImage({
count: 1, // 头像只上传1张
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
success: async (chooseImageRes) => {
try {
const tempFilePaths = chooseImageRes.tempFilePaths;
//#ifdef MP-WEIXIN
//ios小程序会自动压缩
if (this.isIphoneX('iPhone')) {
_this.uploadFile(tempFilePaths[0])
} else {
_this.getImage(tempFilePaths[0], true)
}
//#endif
//#ifndef MP-WEIXIN
_this.getImage(tempFilePaths[0], true)
//#endif
} catch (e) {
console.log(e)
_this.$common.checker.alertTip('图片压缩失败!');
}
},
fail(err) {
console.log(err)
}
})
},
/**
* @param {Object} type 是否需要压缩
*/
getImage(file, type=false) {
if (type) {
this.$common.utils.getImageObject(file, img => {
this.$common.utils.compressImg(img, res => {
this.uploadFile(res)
}, (err) => {
this.$common.checker.alertTip(err.errMsg || '图片压缩失败');
})
})
} else {
this.uploadFile(file)
}
},
uploadFile(file) {
let _this = this;
uni.uploadFile({
url: configer.uploadUrl, // 上传地址
filePath: file,
name: 'file',
formData: {
uploadType: 'aaa'
},
header: {
'content-type': 'application/json'
},
success: (res) => {
//上传结果的处理
},
fail: (err) => {
console.log(err)
}
});
}