前言
小程序项目中在实现上传图片时经常采用第三方组件UI,那么使用已经封装好的上传图片组件时页或多或少遇到一些无法处理的情况。
举例:在使用u-upload上传组件时,回显的图片显示感叹号,打印错误结果为404错误,那么这种情况一般出现在上传的图片格式不规范,如:传入的格式不正确,但是在传入过高分辨率的图片时也会导致图片无法显示。
解决思路:在经过反复测试发现,上传文件大小在20M内都可以正常上传、正常回显,但是一旦图片分辨率超过3000x3000时,图片可以正常上传,但回显为感叹号,打印错误输出为404,因此回显成功与否与上传时分辨率大小有密切关联,在上传文件时采用压缩分辨率即可解决此问题。
提示:以下是本篇文章正文内容,下面案例可供参考
一、问题复现
1.上传测试文件
1.上传<=2M图片文件,分辨率为1000x500;
2.上传>=10M图片文件,分辨率为2500x1500;
3.上传<=5M图片文件,分辨率为9000x5500;
回显速度与网速有关,但1和2可以正常显示,第3张图片虽然只有4.5M但显示为感叹号
2.错误信息
在u-upload组件中,通过@error事件可以打印出错误信息,获取此图片的网络接口为200,但打印出错误信息如下:
二、图片压缩
1.创建Canvas标签
由于上传组件我这里是写在子组件中的,所以直接将Canvas标签放在了父页面,当然也可以放在子组件或者无父子关系,但是获取this的时候需要注意定向问题,这里就展示Canvas放在父页面的情况:
代码如下(示例):
<!--调整图片尺寸-->
<canvas style="width:100vw;height:100vw;position:fixed;left:100%;" id="picCanvas" type="2d"></canvas>
2.在u-upload的上传回调中引用压缩方法
代码如下(示例):
afterRead(event) {
//获取上传的文件列表Ps:一次上传多张
let lists = [].concat(event.file);
for (let i = 0; i < lists.length; i++) {
const item = lists[i];
this.formData.files.push({
...item,
status: 'uploading',
message: '上传中'
});
//引用压缩函数Ps:将文件的Url作为参数传入
this.turnDownPic(item.thumb);
//后面利用Uni的uploadFile上传即可
uni.uploadFile({
url: xxxxxx,
//filePath传入压缩后的图片Url,这里的tempSrc声明在data()中
filePath: this.tempSrc,
name: xxxxxx,
header: {
xxxxxx
},
success: (res) => {
xxxxxx
},
fail(err) {
xxxxxx
}
}
}
3.在methods中定义压缩函数
代码如下(示例):
turnDownPic(picSrc) {
//在Uni方法中无法获取到this需要提前指定
var that = this;
//返回Promise否则在压缩未完成时就已经上传了
return new Promise(function(resolve, reject) {
//获取原图片信息
uni.getImageInfo({
src: picSrc,
success: function(res) {
let canvasRatio = 1.2;//定义初始压缩比例,为了提升效率
let picWidth = res.width;//图片原始宽
let picHeight = res.height;//图片原始长
//需要压缩则根据压缩比例进行压缩
while (picWidth > 2500 || picHeight > 1500) {
picWidth = Math.trunc(res.width / canvasRatio)
picHeight = Math.trunc(res.height / canvasRatio)
//如果需要更高效可将0.1提高为0.2
canvasRatio = canvasRatio + 0.1;
}
//若当前分辨率无需压缩则直接返回原Url
if (res.width === picWidth && res.height === picHeight) {
that.tempSrc = thumb;
resolve();
} else {
//以下代码在Canvas标签中生成需要的图片
uni.createSelectorQuery().select('#picCanvas').fields({
node: true,
size: true
}).exec((res) => {
try {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
let dpr = uni.getSystemInfoSync().pixelRatio
canvas.width = picWidth
canvas.height = picHeight
const img = canvas.createImage()
img.src = thumb
img.onload = () => {
ctx.drawImage(img, 0, 0, picWidth, picHeight);
//延迟200ms,防止最终的图片未绘制完毕
setTimeout(() => {
uni.canvasToTempFilePath({
fileType: "jpg",
canvas: canvas,
destWidth: picWidth,
destHeight: picHeight,
success: function(res) {
that.tempSrc = res.tempFilePath;
resolve()
}
})
}, 200)
}
} catch (e) {
//异常后的操作
reject(e);
}
})
}
}
})
});
},
总结
关于图片压缩其实有很多例子都是通过Canvas重新绘制实现的,实现代码都大体相似,最主要是可以降低分辨率,而官方的压缩方法仅针对大小进行压缩,且不太好用,那么利用Canvas就可以实现分辨率的压缩,以上就是关于Uniapp项目使用上传组件时,上传的文件显示感叹号的解决思路,希望我的分享对您有帮助。