使用FileReader读取多文件因异步返回空base64数组如何解决
解决方案
问题根源
FileReader的onloadend是异步回调,你循环启动所有读取任务后直接打印数组时,所有读取操作都还没完成,因此数组为空。
实现方案
核心思路是将每个文件的读取操作封装为Promise,再通过Promise.all等待所有异步任务执行完成后,再处理最终的base64数组。
修改后的完整代码如下:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script> var file; // 单个文件转base64封装 function fileToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = () => resolve(reader.result); reader.onerror = error => reject(error); }) } async function uploadForm() { const fileList = $('#file')[0].files; // 显示加载状态 showMessage('Uploading file..<img width="20px;" src="https://c.tenor.com/XK37GfbV0g8AAAAi/loading-cargando.gif"/>'); try { // 生成所有读取任务的Promise数组 const readTasks = Array.from(fileList).map(file => fileToBase64(file)); // 等待所有任务完成,拿到完整的base64数组 const allfiles = await Promise.all(readTasks); // 所有读取完成后再打印和后续处理 console.log(JSON.stringify(allfiles)); showMessage("Uploaded"); } catch (err) { console.error('文件读取失败:', err); showMessage("文件读取失败,请重试"); } } function showMessage(e) { $('#progress').html(e); $('#file').val(''); } </script> <table cellpadding="5px"> <tr> <td>Select File:</td> <td> <input id="file" type="file" value="" accept=".csv,.xlsx,.docx,.rtf,.pdf,.pptx,.txt" multiple> </td> </tr> <tr> <td colspan="2"><button onclick="uploadForm(); return false;">Upload</button> </td> </tr> <tr> <td colspan="2"> <div id="progress"></div> </td> </tr> </table>
主要改动说明
- 封装了
fileToBase64工具方法,将回调形式的异步读取转为Promise实例,便于批量管理异步任务 - 上传函数改为async异步函数,使用
await Promise.all()等待所有文件读取完成,此时拿到的数组才包含所有base64数据 - 调整了状态提示的触发顺序,点击上传后立刻显示加载状态,全部读取完成后再更新为成功状态
- 新增异常捕获逻辑,避免单个文件读取失败导致整个流程中断
内容的提问来源于stack exchange,提问作者Code Guy
相关产品推荐
相关产品推荐

