使用FileReader上传文件随机触发DOMException错误求排查与优化方案
问题分析与解决方案
错误原因
这个随机触发的DOMException,常见诱因有以下几种:
- 文件本地状态变更:用户选完文件后,在
FileReader读取完成前,手动移动、删除或重命名了本地文件,导致浏览器无法访问原文件路径。 - 文件引用失效:部分浏览器中,文件输入框的
File对象引用可能因页面异步延迟、后台进程占用等原因失效——虽然fileInput.files仍显示有文件,但实际已无法读取。 - 受保护目录/同步冲突:文件存放在OneDrive、系统临时目录这类受保护或实时同步的位置时,读取过程中刚好遇到权限变更或同步锁,导致读取失败。
解决方法
- 提前锁定文件引用:在上传触发时立即取出
File对象并保存,避免后续重复从DOM元素获取,防止引用失效。 - 添加重试机制:针对这类偶发错误,允许用户一键重试(或自动重试1次)——既然用户重新上传能成功,说明文件本身无问题。
- 前置文件可用性检查:读取前先验证文件的基本属性(如
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
相关产品推荐
相关产品推荐

