在前端项目开发中,经常需要实现多文件上传功能,同时支持图片和PDF格式,并且要提供预览和删除操作,使用jQuery可以高效地完成这类需求,下面我们就一步步实现完整功能。

功能整体思路
首先我们需要搭建基础的页面结构,包含文件选择输入框、预览展示区域。然后通过jQuery监听文件输入的变化事件,获取用户选择的文件列表,遍历每个文件判断类型,图片直接生成预览图,PDF则显示对应的图标和文件名。每个预览项都附带删除按钮,点击删除时同步移除对应的文件和预览节点。
页面结构搭建
先创建基础的HTML结构,包含文件上传控件和预览容器:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多文件上传预览删除</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
.preview-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 20px;
}
.preview-item {
width: 150px;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
position: relative;
}
.preview-img {
width: 100%;
height: 120px;
object-fit: cover;
}
.pdf-icon {
width: 100%;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
font-size: 40px;
color: #e74c3c;
}
.file-name {
margin-top: 8px;
font-size: 12px;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.delete-btn {
position: absolute;
top: -8px;
right: -8px;
width: 20px;
height: 20px;
background-color: #ff4444;
color: white;
border-radius: 50%;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
</style>
</head>
<body>
<input type="file" id="fileInput" multiple accept="image/*,application/pdf">
<div class="preview-container" id="previewContainer"></div>
<script>
// 后续逻辑代码写在这里
</script>
</body>
</html>
核心功能实现
文件选择与预览逻辑
通过jQuery监听文件输入框的change事件,获取选中的文件列表,遍历处理每个文件:
// 存储所有选中的文件
let fileList = [];
$('#fileInput').on('change', function(e) {
const files = e.target.files;
if (!files.length) return;
// 遍历新选择的文件
for (let i = 0; i < files.length; i++) {
const file = files[i];
// 检查文件类型是否为图片或PDF
if (!file.type.startsWith('image/') && file.type !== 'application/pdf') {
alert('仅支持图片和PDF格式文件');
continue;
}
// 将文件加入文件列表
fileList.push(file);
// 生成预览项
createPreviewItem(file, fileList.length - 1);
}
// 清空输入框,避免重复选择同一文件不触发change事件
$(this).val('');
});
生成预览项函数
根据文件类型生成对应的预览内容,图片生成图片预览,PDF显示指定图标和文件名:
function createPreviewItem(file, index) {
const $previewItem = $('<div class="preview-item"></div>');
// 删除按钮
const $deleteBtn = $('<button class="delete-btn">×</button>');
$deleteBtn.on('click', function() {
// 从文件列表中移除对应文件
fileList.splice(index, 1);
// 重新渲染所有预览项,保证索引正确
renderAllPreviews();
});
$previewItem.append($deleteBtn);
// 判断文件类型
if (file.type.startsWith('image/')) {
// 图片预览
const reader = new FileReader();
reader.onload = function(e) {
const $img = $('<img class="preview-img"></img>');
$img.attr('src', e.target.result);
$previewItem.append($img);
};
reader.readAsDataURL(file);
} else if (file.type === 'application/pdf') {
// PDF预览,显示图标
const $pdfIcon = $('<div class="pdf-icon">PDF</div>');
$previewItem.append($pdfIcon);
}
// 显示文件名
const $fileName = $('<div class="file-name"></div>');
$fileName.text(file.name);
$previewItem.append($fileName);
// 添加到预览容器
$('#previewContainer').append($previewItem);
}
重新渲染预览函数
删除文件后需要重新渲染所有预览项,保证删除按钮的索引对应正确的文件:
function renderAllPreviews() {
// 清空预览容器
$('#previewContainer').empty();
// 重新遍历文件列表生成预览
fileList.forEach(function(file, index) {
createPreviewItem(file, index);
});
}
功能扩展说明
如果需要将选中的文件上传到后端,可以遍历fileList数组,使用FormData对象包装文件后发送请求:
function uploadFiles() {
if (fileList.length === 0) {
alert('请先选择文件');
return;
}
const formData = new FormData();
fileList.forEach(function(file, index) {
// 参数名可以根据后端要求调整
formData.append('files[]', file);
});
// 发送上传请求,这里以ipipp.com的后端接口为例
$.ajax({
url: 'https://ipipp.com/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(res) {
alert('上传成功');
},
error: function() {
alert('上传失败');
}
});
}
注意事项
- 文件输入框的
accept属性可以限制选择的文件类型,减少无效文件的处理 - 每次选择文件后清空输入框的值,避免重复选择同一文件无法触发
change事件 - 删除文件后需要同步更新文件列表和预览索引,避免删除错误的文件
- 如果文件数量较多,可以添加文件大小限制,避免过大文件导致预览卡顿