如何在前端动态筛选并上传指定文件(跳过已删除项)

14次阅读

如何在前端动态筛选并上传指定文件(跳过已删除项)

html 文件输入框的 `files` 属性是只读的 filelist 对象,无法直接修改或删除其中某一项;正确做法是维护一个独立的文件引用数组,在上传时按需过滤,而非尝试篡改原生 input.files。

在实现多文件上传并支持“删除预览文件”功能时,一个常见误区是试图直接操作 元素的 files 属性(例如用 splice() 或 delete),但这是无效的——因为 input.files 是只读的类数组对象(FileList),任何对其的修改都不会反映到实际数据上,也不会触发 dom 更新。

✅ 正确思路:脱离原生 files,转而维护一个可变的 javaScript 数组(如 selectedFiles = []),并在用户选择文件后、删除操作时、上传前分别管理该数组。

✅ 推荐实现步骤

  1. 监听 change 事件,将 e.target.files 转为真实数组并存入变量

    let selectedFiles = [];  document.getElementById("fileInput").addEventListener("change", function(e) {   if (e.target.files.length > 0) {     selectedFiles = Array.from(e.target.files); // ✅ 可增删改的真实数组     displayFiles(); // 渲染预览列表(含删除按钮)   } });
  2. 实现 removeFile(index):从 selectedFiles 中删除,而非操作 input.files

    立即学习前端免费学习笔记(深入)”;

    function removeFile(index) {   selectedFiles.splice(index, 1); // ✅ 安全删除   displayFiles(); // 重新渲染剩余文件 }
  3. displayFiles() 示例:生成带删除按钮的预览列表

    function displayFiles() {   const list = document.getElementById("fileList");   list.innerHTML = "";   selectedFiles.forEach((file, i) => {     const li = document.createElement("li");     li.innerhtml = `       ${file.name} (${(file.size / 1024).toFixed(1)} KB)            `;     list.appendChild(li);   }); }
  4. 上传时:仅遍历 selectedFiles 数组构造 FormData

    function uploadFiles() {   const formData = new FormData();   selectedFiles.forEach(file => {     formData.append("files[]", file); // ✅ 使用当前有效文件   });    fetch("/upload", {     method: "POST",     body: formData   })   .then(res => res.json())   .then(console.log)   .catch(console.error); }

⚠️ 注意事项

  • ❌ 不要尝试 input.files.splice()、delete input.files[i] 或赋值 input.files = newArray —— 浏览器会静默忽略;
  • ✅ FileList 只能读取,所有“删除”逻辑必须基于你自己的数组副本;
  • 若需保留原始选择顺序或支持取消再选,可额外记录 input 的 value 或使用 DataTransfer 模拟(进阶场景);
  • 在生产环境建议增加文件类型/大小校验、防重复提交、上传进度反馈等健壮性处理。

通过这种「解耦式管理」,你既能自由控制待上传文件集合,又能保持 ui 与数据状态严格同步,是现代多文件交互的标准实践。

text=ZqhQzanResources