AngularJS结合xlsx实现Excel上传报错Cannot read properties of null(reading '0')
报错原因
触发Cannot read properties of null (reading '0')的核心原因是事件目标取错了:
你给Upload按钮绑定了ng-click事件,触发点击时$event.target指向的是这个type="button"的普通按钮元素,这类元素本身不存在files属性,访问mE.target.files得到的返回值是null,再去读取null[0]就直接抛出类型错误。
你原本的逻辑是想从文件选择框里拿用户选中的Excel文件,但文件选择框是单独的<input id="file-upload" type="file"/>元素,和触发点击的Upload按钮不是同一个DOM节点,自然拿不到文件对象。
修复方案
- 不要从点击事件的target上取files,直接通过id获取文件选择框元素,再读取用户选中的文件
- 增加空值校验,用户未选择文件时直接给出提示,阻断后续逻辑
- 替换已废弃的
readAsBinaryStringAPI,改用兼容性更好的readAsArrayBuffer读取文件,适配新版xlsx库的解析要求 - 增加文件读取异常捕获,提升交互稳定性
修正后代码
HTML部分
<div> <input id="file-upload" type="file" accept=".xlsx,.xls"/> <input type="button" value="Upload" ng-click="fileUpload()"> </div>
给文件选择框加了
accept属性,限制用户只能选择Excel格式文件,减少非法文件上传的概率
JS逻辑部分
$scope.fileUpload = function() { // 直接通过id获取文件选择框元素 const fileInput = document.getElementById('file-upload'); // 校验是否选中文件 if (!fileInput.files || fileInput.files.length === 0) { alert('请先选择要上传的Excel文件'); return; } const file = fileInput.files[0]; const fileReader = new FileReader(); // 用ArrayBuffer方式读取,替代废弃的binaryString读取方式 fileReader.readAsArrayBuffer(file); fileReader.onload = (e) => { var workBook = XLSX.read(e.target.result, {type: 'array'}); var sheetNames = workBook.SheetNames; var ExcelData = XLSX.utils.sheet_to_json(workBook.Sheets[sheetNames[0]]); console.log(ExcelData); // 后续可在此处编写数据提交、页面渲染等业务逻辑 }; // 捕获文件读取异常 fileReader.onerror = () => { alert('文件读取失败,请重试'); }; };
可选优化项
- 如果要贴合AngularJS的双向绑定写法,可以自定义文件选择指令,实现文件对象的
ng-model绑定,避免手动查询DOM - 可新增文件大小、文件后缀名校验逻辑,拦截不符合要求的上传文件
- 解析大体积Excel时增加loading遮罩,避免页面卡顿引发用户重复点击
内容的提问来源于stack exchange,提问作者Tina
相关产品推荐
相关产品推荐

