基于JavaScript实现图片上传前预览功能
作者:叫我一声阿雷吧
这篇文章主要介绍了如何手把手实现一个实用的 JS 图片上传前预览功能,支持多图选择、格式 / 大小校验、预览图删除等核心功能,感兴趣的小伙伴可以参考一下
案例核心效果
- 页面展示文件上传按钮和预览区域,选择图片后可实时预览,支持多张图片;
- 预览图包含删除按钮,点击可移除对应图片,同时清空文件列表;
- 支持限制图片格式(jpg/png/webp)和大小(示例限制 5MB),不符合条件给出清晰提示;
- 预览图自适应布局,适配 PC 和移动端,样式简约美观;
- 代码精简可复用,核心逻辑封装成函数,便于集成到表单上传场景。

实现思路(极简清晰)
分 3 步落地,逻辑简单易上手,零基础也能快速掌握:
- HTML:搭建文件上传控件(隐藏原生按钮,自定义样式)、预览区域,结构极简;
- CSS:美化上传按钮和预览区域,实现预览图自适应布局,突出交互反馈;
- JS:监听文件选择事件→校验文件格式 / 大小→读取文件内容→生成预览图→绑定删除事件。
完整源码(可直接复制运行)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS 图片上传前预览 | 实战案例</title>
<style>
/* 全局重置(精简规范) */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Microsoft YaHei", sans-serif;
}
/* 页面布局:居中显示 */
body {
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 20px;
background-color: #f5f5f5;
}
/* 标题样式 */
.title {
font-size: 24px;
color: #333;
margin-bottom: 30px;
text-align: center;
}
/* 上传容器 */
.upload-container {
width: 100%;
max-width: 800px;
display: flex;
flex-direction: column;
gap: 20px;
}
/* 自定义上传按钮 */
.upload-btn-wrapper {
position: relative;
display: inline-block;
cursor: pointer;
}
.custom-upload-btn {
padding: 12px 24px;
font-size: 16px;
color: #fff;
background-color: #409eff;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.custom-upload-btn:hover {
background-color: #66b1ff;
}
/* 隐藏原生文件输入框 */
#fileInput {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
/* 提示文本 */
.tip-text {
font-size: 14px;
color: #666;
line-height: 1.5;
}
/* 预览区域 */
.preview-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
/* 预览项 */
.preview-item {
position: relative;
width: 150px;
height: 150px;
border-radius: 6px;
overflow: hidden;
border: 1px solid #eee;
}
/* 预览图片 */
.preview-img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* 删除按钮 */
.delete-btn {
position: absolute;
top: 5px;
right: 5px;
width: 24px;
height: 24px;
background-color: rgba(245, 108, 108, 0.8);
color: #fff;
border: none;
border-radius: 50%;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s ease;
display: none;
}
.preview-item:hover .delete-btn {
display: block;
}
.delete-btn:hover {
background-color: #f56c6c;
}
/* 错误提示 */
.error-tip {
color: #f56c6c;
font-size: 14px;
margin-top: 10px;
}
/* 移动端适配 */
@media (max-width: 500px) {
.title {
font-size: 20px;
}
.preview-item {
width: calc(50% - 7.5px);
height: 120px;
}
.custom-upload-btn {
padding: 10px 20px;
font-size: 15px;
}
}
</style>
</head>
<body>
<h1 class="title">图片上传前预览功能</h1>
<div class="upload-container">
<!-- 自定义上传按钮 -->
<div class="upload-btn-wrapper">
<button class="custom-upload-btn">选择图片</button>
<input type="file" id="fileInput" accept="image/jpeg,image/png,image/webp" multiple>
</div>
<p class="tip-text">支持格式:jpg/png/webp | 单张图片最大:5MB | 可多选</p>
<div class="error-tip" id="errorTip"></div>
<!-- 预览区域 -->
<div class="preview-container" id="previewContainer"></div>
</div>
<script>
// 1. 获取DOM元素
const fileInput = document.getElementById('fileInput');
const previewContainer = document.getElementById('previewContainer');
const errorTip = document.getElementById('errorTip');
// 配置项
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp']; // 允许的图片格式
const MAX_SIZE = 5 * 1024 * 1024; // 最大5MB
// 2. 初始化:监听文件选择事件
fileInput.addEventListener('change', handleFileSelect);
// 3. 处理文件选择逻辑
function handleFileSelect(e) {
// 清空错误提示
errorTip.textContent = '';
// 获取选中的文件列表
const files = e.target.files;
if (!files.length) return;
// 遍历文件列表
Array.from(files).forEach(file => {
// 校验文件格式
if (!ALLOWED_TYPES.includes(file.type)) {
errorTip.textContent += `文件${file.name}格式不支持,仅支持jpg/png/webp!\n`;
return;
}
// 校验文件大小
if (file.size > MAX_SIZE) {
errorTip.textContent += `文件${file.name}超过5MB限制!\n`;
return;
}
// 读取文件并生成预览图
generatePreview(file);
});
// 清空文件输入框(解决重复选择同一文件不触发change事件的问题)
fileInput.value = '';
}
// 4. 生成预览图(核心逻辑)
function generatePreview(file) {
// 创建FileReader对象读取文件
const reader = new FileReader();
// 读取完成回调
reader.onload = function(e) {
// 创建预览项容器
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';
previewItem.dataset.fileName = file.name;
// 创建预览图片
const previewImg = document.createElement('img');
previewImg.className = 'preview-img';
previewImg.src = e.target.result; // 设置图片源为文件Base64编码
previewImg.alt = file.name;
// 创建删除按钮
const deleteBtn = document.createElement('button');
deleteBtn.className = 'delete-btn';
deleteBtn.textContent = '×';
// 绑定删除事件
deleteBtn.addEventListener('click', () => {
previewItem.remove();
});
// 组装预览项
previewItem.appendChild(previewImg);
previewItem.appendChild(deleteBtn);
// 添加到预览区域
previewContainer.appendChild(previewItem);
};
// 以DataURL格式读取文件
reader.readAsDataURL(file);
}
</script>
</body>
</html>核心代码拆解(重点突出,易懂好记)
1. HTML 结构(极简规整)
核心分为 3 部分,功能边界清晰:
upload-btn-wrapper:自定义上传按钮容器,隐藏原生input[type=file],实现样式自定义;tip-text/error-tip:提示文本和错误反馈区域,告知用户格式 / 大小限制;preview-container:预览区域,动态生成预览图和删除按钮。
2. CSS 样式(简约美观,交互友好)
重点关注 3 个核心样式:
- 自定义上传按钮:通过定位隐藏原生文件输入框,用自定义按钮替代,实现样式统一;
- 预览图布局:使用
flex-wrap: wrap实现预览图自动换行,适配多图展示; - 交互反馈:删除按钮默认隐藏,鼠标悬浮预览图时显示,提升操作体验。
3. JS 逻辑(核心中的核心,分步拆解)
文件校验:
- 格式校验:通过
ALLOWED_TYPES数组限制支持的图片格式; - 大小校验:通过
file.size判断是否超过 5MB 限制; - 错误反馈:将校验失败信息统一展示在
errorTip区域,清晰易懂;
文件读取:
- 使用
FileReader对象读取文件,readAsDataURL将文件转为 Base64 编码,实现本地预览; onload回调中生成预览图 DOM,避免读取未完成时操作;
交互优化:
- 清空文件输入框:解决重复选择同一文件不触发
change事件的问题; - 删除功能:点击删除按钮移除对应预览项,操作便捷;
兼容性:
accept属性限制文件选择类型,减少无效文件选择;multiple属性支持多选图片,提升使用效率。
新手常见踩坑点(精准避坑,少走弯路)
- 重复选择同一文件不触发事件? → 未清空
fileInput.value,文件输入框值不变则change事件不触发,需在处理完文件后重置; - 预览图不显示? →
FileReader读取文件是异步操作,需在onload回调中生成预览图,而非直接读取reader.result; - 文件大小校验错误? → 单位换算错误,1MB=1024*1024 字节,需确保
MAX_SIZE计算正确; - 移动端预览图变形? → 未给预览图添加
object-fit: cover,导致图片拉伸,需设置该属性保持比例; - 格式校验失效? →
file.type在不同浏览器中可能存在差异(如 jpg 可能是image/jpg或image/jpeg),需兼容所有可能值。
扩展思路(落地性强,新手可练)
- 预览图压缩:结合 Canvas 实现图片压缩,减少上传体积,提升加载速度;
- 拖拽上传:添加拖拽事件监听,支持将图片拖入预览区域直接上传;
- 上传进度展示:集成 AJAX 上传,添加进度条展示上传进度;
- 预览图排序:添加拖拽排序功能,调整预览图展示顺序;
- 限制上传数量:添加最大上传数量限制,超出后禁用上传按钮并给出提示;
- 原图 / 压缩图切换:支持选择上传原图或压缩后的图片,适配不同场景需求。
核心知识点总结(凝练精准,实战导向)
- File API:掌握
FileReader读取本地文件,readAsDataURL生成 Base64 预览图; - 文件校验:通过
file.type/file.size校验文件格式和大小,提升程序健壮性; - DOM 动态生成:动态创建预览图和删除按钮,实现灵活的交互效果;
- 事件处理:解决文件输入框重复选择同一文件不触发事件的问题;
- 样式自定义:隐藏原生文件输入框,实现自定义上传按钮样式;
- 异步处理:理解
FileReader异步读取文件的特性,避免同步操作导致的错误。
到此这篇关于基于JavaScript实现图片上传前预览功能的文章就介绍到这了,更多相关JavaScript图片预览内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
