上传前预览图像的多种方法

上传前预览图像的多种方法

技术背景

在前端开发中,经常会遇到需要在用户上传图像之前进行预览的需求。这可以提升用户体验,让用户在上传之前确认所选的图像是否正确。实现图像预览的方法有多种,下面将详细介绍不同的实现方式。

实现步骤

使用 URL.createObjectURL()

这是一种高效的方法,通过 URL.createObjectURL() 为选择的文件创建一个临时的 URL,然后将该 URL 赋值给 img 元素的 src 属性。

1
2
3
4
5
6
7
8
9
10
11
<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
var loadFile = function(event) {
var output = document.getElementById('output');
output.src = URL.createObjectURL(event.target.files[0]);
output.onload = function() {
URL.revokeObjectURL(output.src) // free memory
}
};
</script>

使用 FileReader.readAsDataURL()

该方法将文件解析为 Base64 编码的字符串,然后将该字符串赋值给 img 元素的 src 属性。

1
2
3
4
5
6
7
8
9
10
11
12
<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
var loadFile = function(event) {
var reader = new FileReader();
reader.onload = function(){
var output = document.getElementById('output');
output.src = reader.result;
};
reader.readAsDataURL(event.target.files[0]);
};
</script>

单文件预览

以下是一个简洁的单文件预览代码示例:

1
2
<input type="file" oninput="pic.src=window.URL.createObjectURL(this.files[0])">
<img id="pic" />

多文件预览

可以使用 JavaScript 或 jQuery 实现多文件预览。以下是使用 jQuery 的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<input type="file" id="image" name="image[]" multiple /><br/>
<div id="frames"></div>
<script>
$(document).ready(function(){
$('#image').change(function(){
$("#frames").html('');
for (var i = 0; i < $(this)[0].files.length; i++) {
$("#frames").append('<img src="'+window.URL.createObjectURL(this.files[i])+'" width="100px" height="100px"/>');
}
});
});
</script>
</body>

React 中的图像预览

在 React 中,可以使用 URL.createObjectURL() 实现图像预览:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import * as React from 'react'
import { useDropzone } from 'react-dropzone'

function imageDropper() {
const [imageUrl, setImageUrl] = React.useState()
const [imageFile, setImageFile] = React.useState()

const onDrop = React.useCallback(
acceptedFiles => {
const file = acceptedFiles[0]
setImageFile(file)

// convert file to data: url
const reader = new FileReader()
reader.addEventListener('load', () => setImageUrl(String(reader.result)), false)
reader.readAsDataURL(file)
},
[setImageFile, setImageUrl]
)
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop })

return (
<div>
<div {...getRootProps()}>
{imageFile ? imageFile.name : ''}
{isDragActive ? <p>Drop files here...</p> : <p>Select image file...</p>}
<input {...getInputProps()} />
</div>
{imageUrl && (
<div>
Your image: <img src={imageUrl} />
</div>
)}
</div>
)
}

核心代码

以下是一个通用的 JavaScript 函数,用于实现图像预览:

1
2
3
4
5
6
7
8
9
10
function imagePreviewFunc(that, previewerId) {
let files = that.files
previewerId.innerHTML='' // reset image preview element

for (let i = 0; i < files.length; i++) {
let imager = document.createElement("img");
imager.src = URL.createObjectURL(files[i]);
previewerId.append(imager);
}
}

对应的 HTML 代码:

1
2
3
4
5
6
7
8
9
<input accept="image/*" type='file' id="imageInput_1"
onchange="imagePreviewFunc(this, imagePreview_1)" />
<div id="imagePreview_1">This Div for Single Image Preview</div>

<hr />

<input class="form-control" accept="image/*" type='file' id="imageInput_2" multiple="true"
onchange="imagePreviewFunc(this, imagePreview_2)" />
<div id="imagePreview_2">This Div for Multiple Image Preview</div>

最佳实践

  • 内存管理:使用 URL.createObjectURL() 时,在图像加载完成后调用 URL.revokeObjectURL() 释放内存。
  • 兼容性处理:不同浏览器对文件读取和预览的支持可能不同,需要进行兼容性处理,例如处理 IE 浏览器的特殊情况。
  • 错误处理:在读取文件或设置图像 src 属性时,要考虑可能出现的错误,如文件类型不支持等情况。

常见问题

  • 文件类型验证:在预览图像之前,需要验证文件类型是否为图像类型,避免预览非图像文件。可以通过检查文件的 type 属性来实现。
  • 跨浏览器兼容性:不同浏览器对 FileReaderURL.createObjectURL() 的支持可能存在差异,需要进行兼容性测试和处理。例如,IE 浏览器需要使用不同的方法来实现图像预览。
  • 内存泄漏:如果使用 URL.createObjectURL() 创建的对象 URL 没有及时释放,可能会导致内存泄漏。因此,在图像加载完成后,要调用 URL.revokeObjectURL() 释放内存。

上传前预览图像的多种方法
https://119291.xyz/posts/preview-an-image-before-it-is-uploaded/
作者
ww
发布于
2025年5月21日
许可协议