You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FileReader时如何避免出现NotReadable错误?

错误诱发原因
  • 临时文件访问权限过期:该报错是典型的文件引用获取后权限丢失场景,最常出现在移动设备上:安卓10+的分区存储机制限制了Web对本地文件的临时访问时长,若获取文件引用后没有立即读取,系统会自动回收权限;部分定制ROM、微信/抖音等内置WebView也会主动缩短临时文件的有效时长,另外选择云盘、外部SD卡中的未缓存文件时,也会出现权限获取失败的问题。
  • 文件引用被提前释放:如果业务逻辑中存在input.value = ''的重置操作(用于支持重复选择同一个文件),若重置操作放在FileReader读取完成之前执行,会直接销毁已获取的文件引用,导致读取失败。
  • 文件本身异常:选中的文件是0字节空文件、加密文件、正在被其他进程占用的文件、或者已损坏的文件时,也会触发该错误。
  • 浏览器兼容问题:部分旧版本移动浏览器对FileReader的大文件读取有阈值限制,若选中的文件体积超过浏览器限制(通常是500M以上),也会抛出读取异常。
修复方案
  • 优先同步读取文件:获取到files[0]后立即执行readAsDataURL操作,不要在change事件触发后、读取前插入任何异步逻辑(比如接口请求、用户二次确认弹框等),避免权限过期。
  • 调整input重置时机:如果需要支持重复选择同一文件,将input.value = ''的操作放到FileReader的onload或onerror回调执行完成之后,不要提前销毁文件引用。
  • 增加前置校验逻辑:读取前先判断文件的size属性是否大于0,若为0字节直接提示用户重新选择文件,避免无效读取。
  • 异常兜底处理:捕获到NotReadable错误时,直接提示用户重新选择文件,同时清空input的值,避免后续选择同个文件仍然报错。
  • WebView场景适配:如果代码运行在原生APP内嵌的WebView中,需要让原生侧提前申请本地存储读取权限,安卓端可在AndroidManifest中开启android:requestLegacyExternalStorage="true"配置,兼容分区存储限制。

优化后代码示例

$(document).on("change", "input[type='file']", function (event) {
  const input = event.target;
  const files = input.files;
  if (!files || !files[0]) return;
  const selectedFile = files[0];
  // 前置校验文件有效性
  if (selectedFile.size === 0) {
    alert("请选择有效文件,不支持0字节文件");
    input.value = '';
    return;
  }
  const reader = new FileReader();
  reader.onload = () => {
    $(input)
      .closest(".row")
      .find(".attachment-data")
      .val(reader.result.split(",")[1]);
    // 读取完成后再重置input,支持重复选同个文件
    input.value = '';
  };
  reader.onerror = (error) => {
    console.log("reader.onerror", error);
    alert("文件读取失败,请重新选择文件");
    // 读取失败也重置input
    input.value = '';
  };
  // 拿到文件后立即同步读取,不插入任何异步操作
  reader.readAsDataURL(selectedFile);
});

内容的提问来源于stack exchange,提问作者ShafiVayyattukavil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 23:15:03