图片显示不完整

记录一个bug

最近遇到一个非常难搞的问题,花了蛮长的时间才算解决了,这里记录一下自己的解决过程!

图片显示一半

我们的APP里面偶尔出现图片只加载了一部分的问题,但是其他用户显示是正常的,也不算必现,就是偶尔听用户报一下,之前也没有太过关注这个bug了,没有及时去处理,作为了一个遗留问题,延后解决!
随着时间的流逝,突然一个大boss直接将这个bug反馈到我们研发,而且还是比较重要的图片,需要我们马上去处理,之前的债也得补上了!

解决过程

猜想

首先根据我们项目,做了几点思考:
图片是加密的,加密方式是AES的,有个别人只看到图片的一部分,说明:

1.图片的上行是没有问题的

2.可能是下行
3.解密出现问题

验证猜想

1.因为其他人可以正常查看,说明图片上传OK
2.确保图片下载是OK的

我们将正常用户的图片和出问题的图片进行文件大小,md5比对,发现没有异常    

3.确保解密是否正常

我们将解密的图片直接保存到SD卡,然后用相册查看,发现是正常的,说明解密也是OK的   

继续猜想

前面的步骤的确认没有问题,那就只有最后一步了,显示框架的问题!
我们的图片显示使用的是Glide,直接将解密后的文件流传递给Glide,这就比较难搞了,如果是Glide的问题那就真的不太好解决了,接下来的时间就比较茫然和懵逼了,不知道怎么去定位问题了!难道是传递给Glide的流可能有问题,或者流没有关闭。。。。

验证

将正常显示的图片传递给Glide的inputStream比对错误的流,发现流的大小是一样的,各种检查代码也没有什么卵用。。。。

猜想

突然一天中午起床,脑子像开了挂一样,发现了一个惊天秘密,显示图片的逻辑如下:

if(!FileUtils.isFileExist(path)){
    //文件不存在,去下载
}else {
    //文件存在,Glide显示
}

那如果点击预览之后,首先图片不存在,网络加载,退出预览界面,再次进入,那么此时文件已经下载了一部分了,肯定就走else的逻辑,直接显示图片,我们之前有个结论:

如果图片不完整,AES应该是解密不出来的

那么这个时候图片应该不能显示,而不是只显示一部分,和结论矛盾了

验证

抱着试一试的态度,去重现这个场景,点击预览,网络下载图片,然后退出,再次预览,发现必现该bug,那么说明这个结论是错误的:

如果文件不完整,AES也能部分解密

这样的话,这个bug就能解释的通了:

文件没有完全下载,解密只解了一部分,交给Glide也就只显示了一部分

我们又对图片做了磁盘缓存:

     Glide.diskCacheStrategy(DiskCacheStrategy.RESULT).into(imageview);

这次不完整的图片就被Glide缓存了起来,以后每次预览都只显示这个缓存图片,没有机会去加载完整的图片,也就是后面就算每次传递给Glide的流是完整的,有没有去加载这个流的数据!

为了验证是Glide使用了磁盘缓存里面的图片,我直接将Glide的磁盘缓存清理掉:

Glide.get(ApplicationExt.mContext.getApplicationContext()).clearDiskCache();

果然图片正常显示了出来!知道bug出生的原因了,修改也就简单了

完善

1.确保文件完整

上传,下载都加上MD5验证,确保文件本身是没有问题

2.预览的判断

md5一致,并且文件存在才去预览
### Vue-Img-Cutter 图片显示问题的解决方案 在使用 Vue-Img-Cutter 时,如果遇到图片显示的问题,可能与以下因素有关:裁剪框尺寸设置当、图片加载未完成或跨域问题。以下是针对该问题的具体解决方法。 #### 1. 确保裁剪框尺寸适配 Vue-Img-Cutter 的裁剪框默认尺寸可能与图片的实际比例匹配,导致部分图片被裁剪掉。可以通过调整 `width` 和 `height` 属性来确保裁剪框适配图片比例[^1]。例如: ```vue <ImgCutter :width="300" :height="300" v-on:cutDown="cutDown" ></ImgCutter> ``` 在上述代码中,将裁剪框的宽度和高度设置为固定值(如 300x300),以确保裁剪框与图片比例一致。 #### 2. 检查图片加载状态 如果图片尚未完加载就进行裁剪操作,可能会导致图片显示。可以在图片加载完成后触发裁剪功能。通过监听 `onload` 事件,确保图片加载完毕后再绑定到裁剪组件[^1]。例如: ```javascript export default { data() { return { imgSrc: "", }; }, methods: { loadImage() { const img = new Image(); img.src = "https://example.com/your-image.jpg"; img.onload = () => { this.imgSrc = img.src; }; }, }, mounted() { this.loadImage(); }, }; ``` 在模板中绑定 `imgSrc` 到裁剪组件: ```vue <ImgCutter :imgSrc="imgSrc" v-on:cutDown="cutDown" ></ImgCutter> ``` #### 3. 处理跨域图片问题 如果图片来自同的域名,可能会因跨域限制导致图片显示。此时需要确保服务器端支持跨域资源共享(CORS)。如果无法修改服务器配置,可以尝试将图片先下载到本地再进行裁剪。例如: ```javascript methods: { async downloadImage(url) { const response = await fetch(url, { mode: "cors" }); const blob = await response.blob(); return URL.createObjectURL(blob); }, async loadImage() { const localUrl = await this.downloadImage("https://example.com/your-image.jpg"); this.imgSrc = localUrl; }, }, ``` #### 4. 调整裁剪模式 Vue-Img-Cutter 提供了多种裁剪模式,包括自由裁剪和固定比例裁剪。如果当前模式适合图片比例,可能会导致显示。可以通过设置 `fixed` 和 `fixedNumber` 属性来调整裁剪模式。例如: ```vue <ImgCutter :fixed="true" :fixedNumber="[1, 1]" v-on:cutDown="cutDown" ></ImgCutter> ``` 上述代码设置了 1:1 的固定比例裁剪模式,避免因比例失衡导致的图片显示。 --- ### 总结 通过调整裁剪框尺寸、确保图片加载完成、处理跨域问题以及选择合适的裁剪模式,可以有效解决 Vue-Img-Cutter 中图片显示的问题。如果问题仍未解决,建议检查浏览器控制台是否有相关错误提示,并根据具体情况进行调试。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值