FileReader读取图片后为什么有时候显示不出来?

百里婧妍 阅读 364

我在用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);
我来解答 赞 15 收藏
二维码
手机扫码查看
2 条解答
小景景
小景景 Lv1
这个问题我之前也踩过坑,主要有几个可能的原因。

先说最常见的一个:你的reader变量是不是定义在函数外面或者被复用了?如果用户快速连续选择文件,前一个读取还没完成,后一个readAsDataURL就把前一个给覆盖掉了,导致前一个的onload永远不会触发,或者触发时拿到的是后面那个文件的结果。每次读取都应该new一个新的FileReader实例。

另外,如果你是在change事件里写的这段逻辑,记得检查file对象是否真的存在,有时候用户取消选择,file可能是undefined。

不过说实话,既然只是为了预览,用FileReader有点杀鸡用牛刀了。更好的写法是用URL.createObjectURL,性能好很多,不需要把整个文件读成base64字符串,特别是大文件的时候差距很明显。

给你一个封装好的版本:

function previewImage(file, imgElement) {
if (!file || !file.type.startsWith('image/')) {
console.warn('请选择有效的图片文件');
return;
}

// 释放之前的blob URL,避免内存泄漏
if (imgElement.dataset.blobUrl) {
URL.revokeObjectURL(imgElement.dataset.blobUrl);
}

const blobUrl = URL.createObjectURL(file);
imgElement.src = blobUrl;
imgElement.dataset.blobUrl = blobUrl;
}

// 使用方式
const fileInput = document.getElementById('fileInput');
const preview = document.getElementById('preview');

fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
previewImage(file, preview);
});


URL.createObjectURL是同步的,直接返回一个blob://开头的URL指向内存里的文件对象,不用等回调。页面卸载或者图片不再需要的时候记得revokeObjectURL释放内存,不然会一直占着。

如果非要用FileReader也行,但记得每次都new新的实例,别复用:

const reader = new FileReader(); // 每次都要new新的
reader.onload = (e) => {
document.getElementById('preview').src = e.target.result;
};
reader.onerror = () => {
console.error('文件读取失败');
};
reader.readAsDataURL(file);


顺便说一句,base64字符串比原文件大33%左右,大文件转完会很大,img标签加载也慢。预览场景blob URL是更优雅的选择。
点赞 1
2026-03-02 08:11
艳兵 Dev
别用FileReader了,直接用URL.createObjectURL更省事,性能还好。

const img = document.getElementById('preview');
img.src = URL.createObjectURL(file);


一行搞定,不需要回调,不需要等onload,用完记得img.onload的时候revokeObjectURL释放内存就行。
点赞 1
2026-03-02 04:01