You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在jQuery和Laravel中实现单输入框多图/文件上传及预览

多文件上传(支持预览、取消)实现方案

基于你提供的HTML结构,我们可以通过JavaScript结合CSS来实现多文件预览和取消功能,核心思路是用数组维护选中的文件(原生FileList不可修改),为每个文件生成预览项并绑定删除事件。

1. 补充CSS样式

先添加必要的样式,让预览区域和取消按钮正常显示:

.upload__img-wrap {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 15px;
}
.upload__img-box {
    position: relative;
    width: 120px;
    height: 120px;
    border: 1px solid #eee;
    border-radius: 4px;
    overflow: hidden;
}
.upload__img-box img, .upload__pdf-icon {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #f5f5f5;
    font-size: 14px;
    color: #666;
}
.upload__img-close {
    position: absolute;
    top: 5px;
    right: 5px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: rgba(0,0,0,0.6);
    color: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
}

2. JavaScript核心逻辑

添加以下脚本,实现文件选择、预览生成、取消删除功能:

// 获取DOM元素
const fileInput = document.getElementById('files');
const previewWrap = document.querySelector('.upload__img-wrap');
// 用数组维护选中的文件(原生FileList不可修改)
let selectedFiles = [];

// 监听文件选择事件
fileInput.addEventListener('change', function(e) {
    const files = Array.from(e.target.files);
    // 过滤已选中的文件(避免重复添加)
    const newFiles = files.filter(file => !selectedFiles.some(existFile => existFile.name === file.name && existFile.size === file.size));
    selectedFiles = [...selectedFiles, ...newFiles];
    // 生成预览
    renderPreviews();
    // 清空原生input的文件列表,避免重复选择同一文件时不触发change事件
    fileInput.value = '';
});

// 生成预览项函数
function renderPreviews() {
    previewWrap.innerHTML = '';
    selectedFiles.forEach((file, index) => {
        const imgBox = document.createElement('div');
        imgBox.className = 'upload__img-box';
        
        // 区分图片和PDF文件
        if (file.type.startsWith('image/')) {
            const img = document.createElement('img');
            img.src = URL.createObjectURL(file);
            img.alt = file.name;
            imgBox.appendChild(img);
        } else if (file.type === 'application/pdf') {
            const pdfIcon = document.createElement('div');
            pdfIcon.className = 'upload__pdf-icon';
            pdfIcon.innerHTML = 'PDF<br>' + file.name;
            imgBox.appendChild(pdfIcon);
        }

        // 添加取消按钮
        const closeBtn = document.createElement('button');
        closeBtn.className = 'upload__img-close';
        closeBtn.innerHTML = '×';
        closeBtn.addEventListener('click', () => {
            // 移除预览项
            imgBox.remove();
            // 从数组中删除对应文件
            selectedFiles.splice(index, 1);
            // 释放Blob URL,避免内存泄漏
            if (file.type.startsWith('image/')) {
                URL.revokeObjectURL(img.src);
            }
        });

        imgBox.appendChild(closeBtn);
        previewWrap.appendChild(imgBox);
    });
}

// 表单提交时,将数组中的文件添加到FormData
document.querySelector('form').addEventListener('submit', function(e) {
    e.preventDefault();
    const formData = new FormData(this);
    // 清空原有的files[]字段
    formData.delete('files[]');
    // 添加数组中的文件
    selectedFiles.forEach(file => {
        formData.append('files[]', file);
    });
    // 这里可以发送AJAX请求,或者继续表单提交
    // 示例:fetch('/upload', { method: 'POST', body: formData })
});

关键说明

  • 用selectedFiles数组维护选中的文件,解决原生FileList无法修改的问题
  • 预览图片时使用URL.createObjectURL生成临时链接,删除时记得用URL.revokeObjectURL释放内存
  • 重复选择同一文件时,通过清空fileInput.value确保change事件能触发
  • PDF文件显示自定义的预览区域,也可以根据需求替换为PDF图标
  • 表单提交时,需要手动将数组中的文件添加到FormData,替换原生的文件列表

内容的提问来源于stack exchange,提问作者Denis S Maheshwari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:15:39