图片上传预览功能的实现与坑
1. 实现方法
1.1. FileReader
原理:把file对象转换成一段data:base64的字符串,在src插入该字符串。
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>上传图片预览</title>
</head>
<body>
<input type="file" id="file"><br>
<img height="200" id="img">
<script>
document.getElementById('file').onchange = function(){
var file = this.files[0];
var reader = new FileReader();
// 监听reader对象的的onload事件,当图片加载完成时,把base64编码賦值给预览图片
reader.onload = function(event){
document.getElementById('img').src = event.target.result;
}
// 调用reader.readAsDataURL()方法,把图片转成base64
reader.readAsDataURL(file);
}
</script>
</body>
</html>
1.2. URL.createObjectURL
原理:创建一个 File 对象或 Blob 对象的内存URL。该URL 的生命周期和创建它的窗口中的 document 绑定。
document.getElementById('file').onchange = function(){
var file = this.files[0];
document.getElementById('img').src = URL.createObjectURL(file);
}
以上两种方法也都适用于视频,区别在于需要传值到<video>
标签的src。
1.3. IE8兼容
但是!但是!但是!以上方法IE8都不支持,所以只能用ajax把图片上传到服务器,然后返回图片在服务器上的地址,把地址塞到src里去。然而接下来还有如下的这些坑:
- 由于ie8不支持label的for属性,考虑使用js触发input[file]控件。
- 但是IE下 input[file]表单控件,不能用js控制打开文件选择器,必须要手动点击才可以,否则提交表单时会报 “拒绝访问”。无奈考虑把input[file]变透明,遮住设计好的按钮。
- ie8不支持opacity属性,用滤镜实现
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);
2. 应用实例
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>上传图片预览</title>
</head>
<style>
.imglabel{
width: 200px;
height: 120px;
line-height: 120px;
text-align: center;
border: 1px solid #ddd;
border-radius: 3px;
background-color: #f8f8f8;
cursor: pointer;
display: block;
margin: 8px;
}
.imgdiv{
position: relative;
width: 200px;
height: 120px;
border: 1px solid #ddd;
border-radius: 3px;
display: none;
margin: 8px;
}
.imgdiv img{
width: 100%;
height: 100%;
}
.imgdiv span{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
color: #fff;
background-color: #000;
opacity: 0.5;
}
.imgdiv label{
display: inline-block;
width: 48%;
text-align: center;
cursor: pointer;
}
</style>
<body>
<label class="imglabel" id="imglabel1" for="file1">+ 添加正面(人像面)</label>
<div class="imgdiv" id="imgdiv1">
<img class="img" id="img1">
<span>
<label for="file1">重新选择</label>
<label onclick="cancel('file1')">删除</label>
</span>
</div>
<input type="file" id="file1" style="display:none;">
<label class="imglabel" id="imglabel2" for="file2">+ 添加反面(非人像面)</label>
<div class="imgdiv" id="imgdiv2">
<img class="img" id="img2">
<span>
<label for="file2">重新选择</label>
<label onclick="cancel('file2')">删除</label>
</span>
</div>
<input type="file" id="file2" style="display:none;">
</body>
<script>
// 删除方法,清空并触发onchange
function cancel(id) {
document.getElementById(id).value = "";
document.getElementById(id).onchange();
}
// 切换隐藏方法
function triggerImg(index){
if(document.getElementById('file'+index).value == ""){
document.getElementById('imgdiv'+index).style="display:none;"
document.getElementById('imglabel'+index).style="display:block;"
} else {
document.getElementById('imgdiv'+index).style="display:block;"
document.getElementById('imglabel'+index).style="display:none;"
}
}
//URL.createObjectURL方式实现
document.getElementById('file1').onchange = function(){
triggerImg("1");
if(this.value != ""){
var file = this.files[0];
document.getElementById('img1').src = URL.createObjectURL(file);
}
}
// FileReader方式实现
document.getElementById('file2').onchange = function(){
triggerImg("2");
if(this.value != ""){
var file = this.files[0];
var reader = new FileReader();
// 监听reader对象的的onload事件,当图片加载完成时,把base64编码賦值给预览图片
reader.onload = function(event){
document.getElementById('img2').src = event.target.result;
}
// 调用reader.readAsDataURL()方法,把图片转成base64
reader.readAsDataURL(file);
}
}
</script>
</html>