图片上传显示的实现
一、实现思路
通过 input 上传文件时的 event 拿到 File 对象,利用 FileReader 进行读取并转换为 Base64,给 <img />
标签进行回显。
二、实现步骤
1、准备上传入口及图片容器
<input />
标签设置 type 为 file 即为上传组件,可以通过 accept 进行文件类型限制。
accept 可取值如下:
audio/*
:接受所有的声音文件。video/*
:接受所有的视频文件。image/*
:接受所有的图像文件。MIME_type
:一个有效的 MIME 类型,不带参数。
这里以上传图片为例:
<input type="file" accept="image/*" onChange={handleUpload} />
<img src={imgSrc} alt="图片" />
还可以针对具体文件类型,例如:
<input type="file" accept=".jpg, .png" onChange={handleUpload} />
2、获取已上传的文件
使用 onChange 监听上传时的 event 对象,根据 event.currentTarget.files
拿到上传的 FileList。
const handleUpload = (event) => {
console.log(event.currentTarget.files)
}
其中 File 对象就是上传的具体文件,现在要做的就是从这个 File 对象中拿到 url,但可以看到 File 对象并没有 url 属性,这时就要用 FileReader 将拿到的 File 对象转为 <img />
标签所需的 src 属性值。
3、读取文件内容并拿到 URL
FileReader 对象可以读取上面获取到的 File 文件内容,通过 FileReader 的 readAsDataURL()
方法可以将读取到的文件转为 <img />
标签可用的 Data URL(Base64 编码)作为其 src 属性值,实现图片显示。
const handleUpload = (event) => {
const uploadedFile = event.currentTarget.files[0];
// 这里可以顺便限制一下上传图片的大小
if (uploadedFile.size > 2 * 1024000) {
alert('上传的图片不得大于2M,请重新上传!')
} else {
const reader = new FileReader();
// 图片读取完成后的操作
reader.onload = (event) => {
console.log(event.currentTarget.result)
};
// 将读取到的文件转为 url
reader.readAsDataURL(uploadedFile);
}
}
// 输出:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAAWgCAYAAAC/k
4、将拿到的 URL 赋给 img
这里以 React 为例:
const [imgSrc, setImgSrc] = useState('')
const handleUpload = (event) => {
const uploadedFile = event.currentTarget.files[0]
// 这里可以顺便限制一下上传图片的大小
if (uploadedFile.size > 2 * 1024000) {
alert('上传的图片不得大于2M,请重新上传!')
} else {
const reader = new FileReader()
// 图片读取完成后的操作
reader.onload = (event) => {
const fileUrl = event.currentTarget.result
setImgSrc(fileUrl)
}
// 将读取到的文件转为 url
reader.readAsDataURL(uploadedFile)
}
}
return (
<div>
<input type="file" accept="image/*" onChange={handleUpload} />
<img src={imgSrc} alt="图片" />
</div>
)
实现效果:
5、优化拿到的图片样式
这里用一个固定宽高的容器包裹图片,并实现里面图片的居中显示及超出部分裁剪:
<div>
<input type="file" accept="image/*" onChange={handleUpload} />
<div className="img-container">
<img src={imgSrc} alt="图片" />
</div>
</div>
容器需要使用 flex
布局,图片使用 object-fit: cover;
实现裁剪。
.img-container {
width: 200px;
height: 200px;
border: 1px solid #e5e5e6;
display: flex;
img {
min-width: 100%;
min-height: 100%;
object-fit: cover;
}
}
效果如下:
- 优化前:
- 优化后: