使用FileReader预览未上传多文件时,如何删除单个文件避免上传?
嘿,我完全懂你遇到的这个麻烦!你明明在前端删掉了图片预览,结果提交表单的时候那些“已删除”的文件还是被传去了服务器——这都是因为input.files返回的FileList是个只读对象,你没法直接删除里面的项。
不用慌,咱们不用彻底重写现有代码,只需要加个小的跟踪逻辑就能解决问题。核心思路是:用一个可修改的数组来记录用户真正想上传的文件,而不是依赖原生的FileList,具体改法如下:
关键改动步骤
新增一个数组来存储待提交的文件
在你的JS代码开头,定义一个数组用来替代原生的FileList,因为数组可以自由增删元素:let selectedFiles = [];修改预览逻辑,给每个预览项绑定文件索引
调整imagesPreview函数,把选中的文件先加入数组,同时给每个预览DOM元素加上对应的数组索引,这样删除时能精准定位到要移除的文件:$(function() { let selectedFiles = []; // 用来保存用户最终要提交的文件 var imagesPreview = function(input, placeToInsertImagePreview) { if (input.files) { var filesAmount = input.files.length; for (i = 0; i < filesAmount; i++) { const file = input.files[i]; selectedFiles.push(file); // 将文件加入跟踪数组 var reader = new FileReader(); // 用闭包保存当前文件的索引,避免循环结束后索引值混乱 (function(fileIndex) { reader.onload = function(event) { // 给预览div加上data-file-index属性,关联数组索引 $('<div class="previewdeleter position-relative" data-file-index="' + fileIndex + '" style="height:200px;width: 200px; display: inline-block; position: relative !important;">' + '<img alt="" src='+event.target.result+' style="height:200px;width: 100%; display: inline-block;">' + '<div class="position-absolute" style="top: 0;right: 0;">' + '<img src="/x.png" class="image-deletepreview" style="height: 20px; display: inline-block;"></div></div>') .appendTo(placeToInsertImagePreview); } })(i); reader.readAsDataURL(file); } // 把删除事件绑定移到循环外,避免重复绑定多次 $('.image-deletepreview').off('click').on('click', function(e) { e.preventDefault(); const previewDiv = $(this).closest('.previewdeleter'); const fileIndex = parseInt(previewDiv.data('file-index')); // 从跟踪数组里移除对应的文件 selectedFiles.splice(fileIndex, 1); // 更新后续预览项的索引,防止索引错位 previewDiv.nextAll('.previewdeleter').each(function(index) { $(this).data('file-index', fileIndex + index); }); // 删除预览DOM previewDiv.remove(); }); } }; // 绑定文件选择事件(假设你原本就是这么调用预览函数的) $('#images').on('change', function() { imagesPreview(this, '#previewHolder'); });表单提交时用跟踪数组构造FormData
最后,在表单提交的时候,不要用原生input的files,而是把我们跟踪数组里的文件加入FormData再提交:// 监听表单提交事件 $('form').on('submit', function(e) { e.preventDefault(); const formData = new FormData(); // 把选中的文件加入FormData selectedFiles.forEach(file => { formData.append('images[]', file); }); // 这里用AJAX提交FormData(替换成你的上传接口) $.ajax({ url: '/your-upload-endpoint', type: 'POST', data: formData, processData: false, // 必须设置,不然jQuery会处理FormData导致错误 contentType: false, // 必须设置,让浏览器自动设置正确的Content-Type success: function(res) { console.log('上传成功!', res); }, error: function(err) { console.error('上传失败', err); } }); }); });
为什么这个方法可行?
这个方案没有修改你原本的预览、删除DOM的逻辑,只是在原有基础上增加了一个“文件跟踪层”:
- 用可修改的数组替代了只读的FileList,解决了无法删除文件的问题
- 通过
data-file-index关联预览项和数组元素,删除时能精准操作 - 提交时用数组里的文件构造FormData,确保只有用户真正保留的文件被上传
这样你不用重写整个上传逻辑,只需要在现有代码上做这些小改动就搞定啦!
内容的提问来源于stack exchange,提问作者Dimi
相关产品推荐
相关产品推荐

