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

使用FileReader上传文件随机触发DOMException错误求排查与优化方案

问题分析与解决方案

错误原因

这个随机触发的DOMException,常见诱因有以下几种:

  • 文件本地状态变更:用户选完文件后,在FileReader读取完成前,手动移动、删除或重命名了本地文件,导致浏览器无法访问原文件路径。
  • 文件引用失效:部分浏览器中,文件输入框的File对象引用可能因页面异步延迟、后台进程占用等原因失效——虽然fileInput.files仍显示有文件,但实际已无法读取。
  • 受保护目录/同步冲突:文件存放在OneDrive、系统临时目录这类受保护或实时同步的位置时,读取过程中刚好遇到权限变更或同步锁,导致读取失败。

解决方法

  1. 提前锁定文件引用:在上传触发时立即取出File对象并保存,避免后续重复从DOM元素获取,防止引用失效。
  2. 添加重试机制:针对这类偶发错误,允许用户一键重试(或自动重试1次)——既然用户重新上传能成功,说明文件本身无问题。
  3. 前置文件可用性检查:读取前先验证文件的基本属性(如size、name),提前过滤无效引用。

代码优化建议

优化后的代码

//Upload the file.
function uploadFile() {
  const fileInput = jQuery('#getFile');
  const newName = jQuery('#displayName').val();
  // 提前获取文件对象,锁定引用
  const file = fileInput[0].files?.[0];
  
  if (!file) {
    alert('请选择要上传的文件');
    return;
  }

  // 用原生Promise替代jQuery Deferred,更贴合现代JS标准
  getFileBuffer(file)
    .then(arrayBuffer => addFileToFolder(arrayBuffer))
    .then(() => {
      // 替换alert为更友好的页面提示(建议用页面元素展示而非弹窗)
      console.log('上传完成');
      // 示例:document.getElementById('uploadStatus').textContent = '上传完成';
    })
    .catch(error => {
      onError(error);
      // 针对文件找不到的错误,提示用户重试
      if (error.name === 'NotFoundError') {
        if (confirm('文件读取失败,是否重试?')) {
          uploadFile();
        }
      }
    });

  // 获取文件的ArrayBuffer,参数传入提前锁定的file对象
  function getFileBuffer(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = (e) => resolve(e.target.result);
      reader.onerror = (e) => reject(e.target.error);
      // 前置检查文件是否可读
      try {
        // 尝试访问文件属性,验证引用有效性
        if (file.size === 0) throw new Error('空文件无法上传');
        reader.readAsArrayBuffer(file);
      } catch (err) {
        reject(err);
      }
    });
  }

  // 上传到SharePoint,补充完整错误处理与必要headers
  function addFileToFolder(arrayBuffer) {
    return jQuery.ajax({
      url: fileCollectionEndpoint,
      type: "POST",
      data: arrayBuffer,
      processData: false,
      headers: {
        "accept": "application/json;odata=verbose",
        "content-length": arrayBuffer.byteLength,
        // 补充SharePoint上传通常需要的请求摘要(根据实际环境调整)
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
      }
    }).fail((jqXHR, textStatus) => {
      throw new Error(`上传到SharePoint失败:${textStatus}`);
    });
  }
}

function onError(error) {
  console.error('上传错误详情:', error);
  alert(`上传失败:${error.message}`);
}

优化点说明

  • 提前锁定文件引用:函数开头就取出File对象,避免后续依赖DOM元素的动态引用,降低失效概率。
  • 原生Promise替代jQuery Deferred:符合现代JS标准,减少第三方依赖,代码更简洁。
  • 全链路错误处理:覆盖FileReader读取、SharePoint上传的所有错误场景,并针对目标错误提供重试选项。
  • 前置有效性检查:尝试访问file.size提前发现无效引用,减少不必要的读取操作。
  • 用户体验优化:建议用页面内提示元素替代alert弹窗,同时补充SharePoint上传所需的X-RequestDigest(按需调整)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:11:10