实现多张图片压缩及上传
需求
表单内容中包含图片(可能多张),采取方法是先请求多次将图片上传,将图片上传后返回的链接放到表单请求体中,再提交表单内容。
思路
使用Promise.all将图片全部上传之后再提交表单
const promises = imageList.value.map(it => uploadFile(it))
Promise.all(promises).then((res: any) => {
postRequest.images = res.map((val: any) => {
return import.meta.env.VITE_APP_BASE_URL val.data.url
}).join(';')
return postExposure(postRequest) //提交表单请求
}).then((res) => {
if(res.status === 0) {
Toast.success('发布成功!')
}
}).catch((err) => {
else Toast.fail('发布失败!')
})
经过了一番波折,解决了图片上传的问题后,考虑到图片大小,决定先上传再压缩。
经过一番比较,决定使用compressorjs这个库。(别问为啥不自己写,问就是折腾了好久没折腾出来)
compressorjs
的基本使用
install
npm install compressorjs
基本使用
import Compress from 'compressorjs'
new Compressor(file, {
quality: 0.6, //图片压缩比例,取值范围为0~1
success(result) {
const formData = new FormData();
formData.append('file', result, result.name);
//上传图片请求 示例,使用时替换成自己的上传请求即可
axios.post('/post/upload', formData).then((res) => {
console.log('上传成功');
})
},
error(err) {
console.log(err.message)
}
})
通过之前自己写压缩图片方法过程中对图片压缩的一些了解,我知道这个压缩图片方法是异步的。这意味着我不能直接像下面这样将它放到我之前的代码中
const promises = imageList.value.map(it => {
new Compressor(it.file, {
quality: 0.6,
success(result) {
const formData = new FormData();
formData.append('file', result, result.name);
return uploadFile(formData)
}
})
}
这样的写法明显是错误的(然而第一次尝试的我并不知道,因此踩了一次坑)
由于此压缩过程是异步的,因此promises
中全为undefined
。
经过了一番思索,最终我将代码改成了这样
/** 压缩图片 */
async function compressImage(file) {
return new Promise((resolve, reject) => {
new Compressor(file, {
quality: 0.6,
convertTypes: ['image/png', 'image/jpg'],
convertSize: 1000000,
success(result) {
resolve(result)
},
error(err) {
reject(err)
}
})
})
}
/** 发布 */
function onPost() {
const promises = imageList.value.map(async (val: any) => {
if(val.file.size <= 1024*1024) {
//小于1MB时不压缩直接上传
return uploadFile(val)
} else {
const result = await compressImage(va file)
const formData = new FormData()
formData.append('file', result, resul name)
return uploadFile(formData)
}
})
Promise.all(promises).then((res: any) => {
postRequest.images = res.map((val: any) => {
return import.meta.env.VITE_APP_BASE_URL val.data.url
}).join(';')
return postExposure(postRequest)
}).then((res) => {
if(res.status === 0) {
Toast.success('发布成功!')
}
}).catch((err) => {
else Toast.fail('发布失败!')
})
}
到此,总算是解决了压缩多张图片并上传的问题。
但是,其实这里还存在一些问题,比如没有处理图片上传失败的情况。需要根据情况改进~