
本文详解如何使用 javascript(配合 formdata 和 map)在多文件上传场景中,准确管理用户选择的图片列表,实现在预览时删除某张缩略图后,该图片不再随表单提交发送至服务器。
本文详解如何使用 javascript(配合 formdata 和 map)在多文件上传场景中,准确管理用户选择的图片列表,实现在预览时删除某张缩略图后,该图片不再随表单提交发送至服务器。
在传统多图上传表单中,<input type="file" multiple> 的 files 属性是只读的,无法按需移除其中某个文件对象——这正是你遇到的核心问题:点击“Deletar”仅移除了 DOM 中的预览元素,但原始 input.files 未改变,导致所有图片仍被完整提交。要真正实现「逻辑删除」,必须脱离对原生 input.files 的依赖,转而用 JavaScript 自主维护一份可增删的文件引用集合。
我们采用 Map 对象作为文件状态管理器,每个文件以唯一 ID(如 id${lastModified}${size})为键,存储其元信息(name, type, lastModified, size)及 Base64 数据 URL(src)。这样既能保留文件语义,又支持高效查删。
✅ 关键实现步骤
-
拦截文件选择,存入 Map
不再直接监听 input#imagens 的 change,而是监听隐藏 <input name="images"> 的 input 事件,遍历 e.target.files,用 FileReader 读取每张图,并将解析后的文件信息存入 images Map:
document.forms.form01.images.addEventListener('input', e => {
const input = e.target;
[...input.files].forEach(file => {
const reader = new FileReader();
reader.fileinfo = { name: file.name, lastModified: file.lastModified, size: file.size, type: file.type };
reader.onload = e => {
const fileObj = { ...reader.fileinfo, src: e.target.result };
const id = `id${file.lastModified}${file.size}`;
images.set(id, fileObj);
previewImages(); // 刷新预览
};
reader.readAsDataURL(file);
});
input.value = ''; // 清空 input,允许重复选择相同文件
});-
点击删除按钮 → 从 Map 移除对应项
每个删除按钮的 value 绑定其所属图片的唯一 ID,点击时调用 images.delete(id),随后触发 previewImages() 同步 UI:
document.forms.form01.addEventListener('click', e => {
if (e.target.name === 'delete') {
images.delete(e.target.value);
previewImages();
}
});-
表单提交时,手动构造 FormData
阻止默认提交,遍历 images Map,将每张图转换为 Blob(通过 dataURItoBlob 工具函数),再追加到 FormData 中:
document.forms.form01.addEventListener('submit', e => {
e.preventDefault();
const formData = new FormData(e.target);
formData.delete('images'); // 移除原始空 input 字段
images.forEach((file, id) => {
const blob = dataURItoBlob(file.src);
formData.append('imagens[]', blob, file.name); // 注意:后端字段名保持为 'imagens[]'
});
fetch('post.php', {
method: 'POST',
body: formData
})
.then(res => res.json())
.then(data => console.log('Upload success:', data))
.catch(err => console.error('Upload failed:', err));
});⚠️ 注意事项:
- 后端接收字段名需与 formData.append('imagens[]', ...) 一致(即 $_FILES['imagens']),而非原 HTML 中的 name="imagens[]" —— 因为原 input 已被隐藏且不参与提交。
- dataURItoBlob 函数必须正确解析 Base64 数据并还原 MIME 类型,否则后端可能收到损坏文件。
- 删除按钮需设为 type="button" 并显式指定 name="delete",避免意外触发表单提交。
? 总结
真正的「删除图片」不是视觉移除,而是从待提交数据源中剔除该文件的引用。通过 Map + FileReader + FormData 的组合方案,你完全掌控了文件生命周期:添加、预览、删除、提交,各环节解耦清晰,逻辑健壮。此模式也易于扩展(如支持排序、裁剪、压缩等),是现代 Web 文件交互的最佳实践之一。
立即学习“前端免费学习笔记(深入)”;
















