FileReader读取图片后为什么有时候显示不出来?
我在用FileReader做图片预览功能,选了图片后调用readAsDataURL,但有时候onload回调里拿到的result赋值给img的src却显示空白,控制台也没报错。
我试过在onload里加console.log,发现result字符串是有的,格式也对,但图片就是不显示。是不是和文件大小或者类型有关?代码大概是这样:
const reader = new FileReader();
reader.onload = (e) => {
const img = document.getElementById('preview');
img.src = e.target.result; // 有时候这里没生效
};
reader.readAsDataURL(file);
先说最常见的一个:你的reader变量是不是定义在函数外面或者被复用了?如果用户快速连续选择文件,前一个读取还没完成,后一个readAsDataURL就把前一个给覆盖掉了,导致前一个的onload永远不会触发,或者触发时拿到的是后面那个文件的结果。每次读取都应该new一个新的FileReader实例。
另外,如果你是在change事件里写的这段逻辑,记得检查file对象是否真的存在,有时候用户取消选择,file可能是undefined。
不过说实话,既然只是为了预览,用FileReader有点杀鸡用牛刀了。更好的写法是用URL.createObjectURL,性能好很多,不需要把整个文件读成base64字符串,特别是大文件的时候差距很明显。
给你一个封装好的版本:
URL.createObjectURL是同步的,直接返回一个blob://开头的URL指向内存里的文件对象,不用等回调。页面卸载或者图片不再需要的时候记得revokeObjectURL释放内存,不然会一直占着。
如果非要用FileReader也行,但记得每次都new新的实例,别复用:
顺便说一句,base64字符串比原文件大33%左右,大文件转完会很大,img标签加载也慢。预览场景blob URL是更优雅的选择。
一行搞定,不需要回调,不需要等onload,用完记得img.onload的时候revokeObjectURL释放内存就行。