FileReader读取图片预览需用readAsDataURL()转base64并赋值img.src,且必须在onload回调中获取reader.result;上传前须校验file.type和file.size,FormData上传时append的必须是File对象而非base64字符串。
直接用 readAsDataURL() 把 File 对象转成 base64 字符串,再赋给 的 src 属性即可。注意必须等 onload 触发后再取 result,否则是空值。
FileReader 是异步的,readAsDataURL() 调用后立刻返回,内容在 onload 里才可用onload 外访问 reader.result,它此时还是 null
max-width: 100%),避免大图撑破容器const reader = new FileReader();
reader.onload = function() {
const img = document.getElementById('preview');
img.src = reader.result; // 这里才是有效的 data URL
};
reader.readAsDataURL(file); // file 来自 input[type="file"].files[0]不能只靠 accept 属性——它只是提示,用户可绕过。必须在 JS 里用 file.type 和 file.size 做实际校验。
file.type 可能为空(比如拖拽 txt 文件),优先用文件扩展名或 file.name.split('.').pop() 辅助判断file.size 单位是字节,1MB = 1048576 字节,别写成 1000000event.preventDefault() 阻止后续逻辑,并给出明确提示if (file.size > 2 * 1048576) {
alert('文件不能超过 2MB');
return;
}
if (!file.type.startsWith('image/')) {
alert('仅支持图片文件');
return;
}常见原因是没给 FormData.append() 的第二个参数传入 File 对象本身,而是传了字符串、reader.result 或其他无效值。
FormData.append('file', file) 才正确;传 reader.result 是传 base64 字符串,后端收到的是文本字段,不是文件流FormData.append('desc', 'xxx') 即可,和文件一起发fetch 发送时不要手动设 Content-Type,让浏览器自动设置带 boundary 的 multipart/form-dataconst formData = new FormData();
formData.append('file', file); // ← 必须是 file 对象
formData.append('name', 'avatar');
fetch('/upload', {
method: 'POST',
body: formData // 不要加 headers: { 'Content-Type': ... }
});
IE10+ 支持 FileReader,但 IE 不支持 URL.createObjectURL()(虽然这里不用它)。真正要注意的是移动端 Safari 对大图 readAsDataURL() 的内存限制——超 10MB 容易卡死或中断。
URL.createObjectURL(file) 做预览(更快、不占内存),上传仍用原 File 对象createObjectURL 创建的 URL 必须在不用时调用 URL.revokeObjectURL() 释放引用,否则内存泄漏FileReader 的 onerror 不触发,建议加 onabort 和超时兜底预览环节能省则省 base64,上传环节别把预览逻辑和上传逻辑耦合太死——它们本就该
