珠峰培训

HTML5实现图片上传与预览

作者:

2017-06-16 16:42:02

795

 

File API

  • File - 独立文件;提供只读信息,例如名称、文件大小、mimetype 和对文件句柄的引用。
  • FileList - File 对象的类数组序列(考虑多文件上传或者从桌面拖动目录或文件)。
  • Blob - 可将文件分割为字节范围。
  • FileReader - 读取File或Blob
  • URL scheme

检测浏览器是否支持

// 检测是否支持File API
if (window.File && window.FileReader && window.FileList && window.Blob) {
// 支持
} else {
alert('不支持');
}

选取一张图片,并预览

<input id="img_input" type="file" accept="image/*"/>
<label for="img_input"></label>
<div class="preview_box"></div>

.preview_box img {
width: 200px;
}
$("#img_input").on("change", function(e){

let file = e.target.files[0]; //获取图片资源

// 只选择图片文件
if (!file.type.match('image.*')) {
return false;
}

let reader = new FileReader();
reader.readAsDataURL(file); // 读取文件

// 渲染文件
reader.onload = function(arg) {
let img = '<img class="preview" src="' + arg.target.result + '" alt="preview"/>';
$(".preview_box").empty().append(img);
}
});

上传到服务器

let form_data = new FormData();
let file_data = $("#img_input").prop("files")[0];

// 把上传的数据放入form_data
form_data.append("user", "hzzly");
form_data.append("img", file_data);

$.ajax({
type: "POST", // 上传文件要用POST
url: "",
dataType : "json",
crossDomain: true, // 如果用到跨域,需要后台开启CORS
processData: false, // 注意:不要 process data
contentType: false, // 注意:不设置 contentType
data: form_data
}).success(function(msg) {
console.log(msg);
}).fail(function(msg) {
console.log(msg);
});

拖拽上传

三个相关事件:

  • dragenter
  • dragover
  • drop
<div id="drop_zone">Drop files here</div>
<ul id="list"></ul>
// 必须阻止dragenter和dragover事件的默认行为,这样才能触发 drop 事件
function fileSelect(evt) {

evt.stopPropagation();
evt.preventDefault();

let files = evt.dataTransfer.files; // 文件对象
let output = [];

// 处理多文件
for (let i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',f.size, ' bytes, last modified: ',f.lastModifiedDate.toLocaleDateString(), '</li>');
}
// 显示文件信息
document.getElementById('list').innerHTML = output.join('');
}

function dragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}

// 监听器
let dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', dragOver, false);
dropZone.addEventListener('drop', fileSelect, false);

美化上传框

方法一: 在隐藏的文件输入框上调用click()方法

隐藏掉默认的的文件输入框元素,使用自定义的界面来充当打开文件选择对话框的按钮。要使用样式display:none把原本的文件输入框隐藏掉,然后在需要的时候调用它的click()方法就行了。

<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">选择文件</a>
let fileSelect = document.getElementById("fileSelect"),
fileElem = document.getElementById("fileElem");

fileSelect.addEventListener("click", function (e) {
if (fileElem) {
fileElem.click(); // jQuery可以使用 trigger()
}
e.preventDefault(); // prevent navigation to "#"
}, false);

方法二:用label

隐藏input,把样式写到label上,点击label就是对input进行操作。

<input id="img_input2" type="file" accept="image/*"/>
<label for="img_input2" id="img_label2">选择文件
<i class="fa fa-plus fa-lg"></i>
</label>
<div id="preview_box2"></div>


#img_input2 {
display: none;
}
#img_label2 {
background-color: #f2d547;
border-radius: 5px;
display: inline-block;
padding: 10px;
}
#preview_box2 img {
width: 200px;
}
$("#img_input2").on("change", function(e) {

let file = e.target.files[0]; //获取图片资源

// 只选择图片文件
if (!file.type.match('image.*')) {
return false;
}

let reader = new FileReader();
reader.readAsDataURL(file); // 读取文件

// 渲染文件
reader.onload = function(arg) {

let img = '<img class="preview" src="' + arg.target.result + '" alt="preview"/>';
$("#preview_box2").empty().append(img);
}
});

使用Base64的方式,实现本地预览

if (window.FileReader) {
let oFileReader = new FileReader(),
oFile = e.target.files[0];
if (/^image*/.test(oFile.type)) {
oFileReader.onloadend = function (e) {
let binfo64 = e.target.result;
let postinfo = {
image: binfo64,
filename: `passport-${new Date().getTime()}`
}
};
oFileReader.readAsDataURL(oFile);
} else {
alert('传入图片文件');
}
}

使用Ajax上传图片信息,并显示图片上传的进度

<form id="fileupload-form">    
<input id="fileupload" type="file" name="file" >
</form>
//绑定了`submit`事件。    
$('#fileupload-form').on('submit',(function(e) {
e.preventDefault();
//序列化表单
var serializeData = $(this).serialize();

// var formData = new FormData(this);
$(this).ajaxSubmit({
type:'POST',
url: *yoururl*,
dataType: 'json',
data: serializeData,
// data: formData,

//attention!!!
contentType: false,
cache: false,
processData:false,

beforeSubmit: function() {
//上传图片之前的处理
},
uploadProgress: function (event, position, total, percentComplete){
//在这里控制进度条
},
success:function(){

},
error:function(data){
alert('上传图片出错');
}
});
}));

//绑定文件选择事件,一选择了图片,就让`form`提交。

$("#fileupload").on("change", function() {
$(this).parent().submit();
});

说明:

  1. 使用.serialize()获取表单的数据,不同通过val和text获取值
  2. ajax上传图片这三个参数必须配置contentType: false, cache: false, processData:false
  3. 该处使用了uploadProgress 来获取文件上传的进度