AJAX多文件单独上传:实现顺序上传、进度条及表单提交控制
多文件串行上传(带进度跟踪)解决方案
问题现状
当前代码会同时发起所有文件的上传请求,导致进度条无法准确对应单个文件的上传状态,且无法判断全部上传完成的时机来提交表单。需要修改为串行上传(完成一个再传下一个),并在全部上传完成后触发表单提交。
修改后的代码
HTML(新增进度条与状态提示)
<div id="dropzone-zone"> <button type="submit" class="btn btn-primary btn-xs" id="add_file" name="add_file" form="upload-form" style="display:none;">Subir archivos</button> <form action="" id="upload-form" method="post" enctype="multipart/form-data"> <div id="dropzone" class="drop-zone" style="display:block;"> <span class="drop-zone__prompt">Haga click o arrastre los archivos que desea subir.</span> <input type="file" name="file-upload[]" style="display:none;" id="file-upload" class="drop-zone__input" multiple> <!-- 单个文件上传进度条 --> <progress id="load-progress" value="0" max="100" style="width:100%;margin-top:10px;"></progress> <!-- 上传状态提示 --> <div id="upload-status" style="margin-top:8px;color:#666;"></div> </div> </form> </div>
JavaScript(改为串行上传+完成判断)
const inputElement = document.getElementById("file-upload"); const dropZoneElement = document.getElementById("dropzone"); const progressBar = document.getElementById("load-progress"); const statusText = document.getElementById("upload-status"); const submitBtn = document.getElementById("add_file"); dropZoneElement.addEventListener("dragover", (e) => { e.preventDefault(); }); dropZoneElement.addEventListener("drop", (e) => { e.preventDefault(); inputElement.files = e.dataTransfer.files; dropZoneElement.querySelector(".drop-zone__prompt").remove(); // 将文件列表转为数组,方便顺序处理 const filesArray = Array.from(inputElement.files); let currentFileIndex = 0; // 递归处理单个文件上传 function uploadNextFile() { if (currentFileIndex >= filesArray.length) { // 所有文件上传完成,提交表单 statusText.textContent = "Todos los archivos se subieron correctamente, enviando formulario..."; submitBtn.click(); return; } const currentFile = filesArray[currentFileIndex]; statusText.textContent = `Subiendo: ${currentFile.name} (${currentFileIndex + 1}/${filesArray.length})`; const formdata = new FormData(); formdata.append("file-upload", currentFile); const ajax = new XMLHttpRequest(); // 监听上传进度 ajax.upload.addEventListener("progress", (event) => { if (event.lengthComputable) { const percent = (event.loaded / event.total) * 100; progressBar.value = Math.round(percent); } }); // 单个文件上传完成后处理下一个 ajax.addEventListener("load", () => { if (ajax.status === 200) { currentFileIndex++; progressBar.value = 0; // 重置进度条 uploadNextFile(); } else { statusText.textContent = `Error al subir ${currentFile.name}, código: ${ajax.status}`; } }); // 网络错误处理 ajax.addEventListener("error", () => { statusText.textContent = `Error de red al subir ${currentFile.name}`; }); ajax.open("POST", "pruebas.php"); ajax.send(formdata); } // 启动第一个文件上传 uploadNextFile(); });
关键修改说明
- 串行上传逻辑:用递归函数
uploadNextFile替代原循环,只有当前文件上传完成(触发load事件)后,才会启动下一个文件的上传,解决进度条混乱问题。 - 进度与状态反馈:新增进度条和状态文本,实时显示当前上传的文件名、进度及总进度。
- 完成判断:当
currentFileIndex等于文件总数时,触发隐藏提交按钮提交表单。 - 错误处理:添加网络错误和服务器错误监听,及时反馈上传异常。
内容的提问来源于stack exchange,提问作者leesin koreano
相关产品推荐
相关产品推荐

