一、使用 FormData
在实现文件上传、导入功能时要传输二进制数据给服务器,所以只能用 FormData 格式。
post 请求,Content-Type必须设置为: multipart/form-data; 。
示例1(fetch):
<input id="file-input" type="file"/>
<a class="J-upload">上传</a>
// 预览
$("#file-input").on("change", function() {
let fileReader = new FileReader(),
fileType = this.files[0].type;
fileReader.onload = function() {
if (/^image/.test(fileType)) {
$(`<img src="${this.result}">`).appendTo("body");
}
};
fileReader.readAsDataURL(this.files[0]);
});
// 上传
$(".J-upload").on("click", function() {
let formData = new FormData(),
input = $("#file-input")[0];
if(!input.files.length){
return alert('请选择文件');
}
formData.append("img", input.files[0]);
fetch("/uploadImg", {
method: "POST",
body: formData
}).then();
});
示例2($.ajax):
<input id="name" />
<input id="upload" type="file" />
var formData = new FormData();
var name = $("#name").val();
formData.append("file",$("#upload")[0].files[0]);
formData.append("name",name);
$.ajax({
url : 'upload.php',
type : 'POST',
data : formData,
cache: false, // 不设置缓存
processData : false, // 不处理发送的数据
contentType : false, // 不设置Content-Type请求头, jquery 会自动设置为multipart/form-data
beforeSend:function(){
console.log("正在进行,请稍候");
},
success : function(responseStr) { },
error : function(responseStr) { }
});
三、多文件上传
多文件上传就是在 file 标签添加 multiple 属性。
//设置 multiple属性
<input id="file-input" type="file" multiple />
<a class="J-upload">上传</a>
$(".J-upload").on("click", function() {
let formData = new FormData(),
input = $("#file-input")[0];
if(!input.files.length){
return alert('请选择文件');
}
//多文件上传需要遍历添加到 fromdata 对象
for(var i = 0; i < input.files.length; i++){
formData.append('img', input.files[i]);
}
fetch("/uploadImg", {
method: "POST",
body: formData
}).then();
});
四、上传进度条
使用iframe没法获取上传进度,但XHR2的 xhr.upload.onprogress 可以实现上传进度条。
注意:xhr.upload.onprogress要写在xhr.send方法前面,否则event.lengthComputable状态不会改变,只有在最后一次才能获得,也就是100%的时候
<div>
选择文件(可多选):
<input type="file" id="f1" multiple/>
<!-- 进度条 -->
<div id="progress">
<span class="red"></span>
</div>
<button type="button" id="btn-submit">上 传</button>
</div>
function submitUpload() {
var progressSpan = document.querySelector('#progress > span');
var fileList = document.getElementById('f1').files;
progressSpan.style.width='0';
progressSpan.classList.remove('green');
if(!fileList.length){
return alert('请选择文件');
}
var fd = new FormData();
for(var i =0; i<fileList.length; i++){
fd.append('f1', fileList[i]);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://10.70.65.235:8100/', true);
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
var obj = JSON.parse(xhr.responseText);
if(obj.fileUrl.length){
//alert('上传成功');
}
}
}
xhr.onprogress=updateProgress;
xhr.upload.onprogress = updateProgress;
function updateProgress(event) {
if (event.lengthComputable) {
// 当前上传进度的百分比
var completedPercent = (event.loaded / event.total * 100).toFixed(2);
progressSpan.style.width= completedPercent+'%';
progressSpan.innerHTML=completedPercent+'%';
if(completedPercent > 90){ //进度条变色
progressSpan.classList.add('green');
}
}
}
xhr.send(fd);
}
//绑定提交事件
document.getElementById('btn-submit').addEventListener('click',submitUpload);
五、拖拽上传
<div class="img-container">
drop your image here
</div>
$(".img-container").on("dragover", function (event) {
// 拖拽图片的时候dragover和drop事件里的默认效果一定要禁掉,不然会变成网页里打开图片的效果
event.preventDefault();
}).on("drop", function(event) {
event.preventDefault();
let file = event.originalEvent.dataTransfer.files[0];
console.log({file})
// 然后就跟处理input获取到的file一样了
});
六、在编辑框里粘贴上传
粘贴的方式,通常是在一个编辑框里操作,如把div的contenteditable设置为true:
<div id="editor" contenteditable="true">
hello, paste your image here
</div>
$("#editor").on("paste", function(event) {
let file = event.originalEvent.clipboardData.files[0];
});
但是Safari的粘贴不是通过event传递的,它是直接在输入框里面添加一张图片,它新建了一个img标签,并把img的src指向一个blob的本地数据。
$("#editor").on("paste", function(event) {
// 需要setTimeout 0等图片出来了再处理
setTimeout(() => {
let img = $(this).find("img[src^='blob']")[0];
console.log(img.src);
}, 0);
});
七、大文件上传
切片上传,断点续传。详情