# 上传
其实无论是原生JS还是xhr,还是jq的ajax,还是axios的异步都提供了一个获取上传进度的API,首先我们来看一下原生js如何获取上传进度。下面的示例代码中,异步上传均采用formData的形式来上传
# 原生JS获取上传进度
var fd = new FormData();
fd.append('file', document.getElementById('testFile').files[0]);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', uploadProgress, false);
xhr.addEventListener('load', uploadComplete, false);
xhr.addEventListener('error', uploadFailed, false);
xhr.addEventListener('abort', uploadCanceled, false);
function uploadProgress(evt) {
if(evt.lengthComputable) {
var percent = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progress').innerHTML = percent.toFixed(2) + '%';// 设置进度显示百分比
document.getElementById('progress').style.width = percent.toFixed(2) + '%';// 设置完成的进度条宽度
} else {
document.getElementById('progress').innerHTML = 'unable to compute';
}
}
# JQ获取上传进度
jq并没有直接提供uplodaProgress方法,但是它提供了一个xhr参数,使用方法如下
var fd = new FormData();
fd.append('file', document.getElementById('testFile').files[0]);
$.ajax({
url: 'http://127.0.0.1:3003/useasync/uploadFile',
type: 'POST',
contentType: 'multipart/form-data',
data: fd,
xhr: function() {
myXhr = $.ajaxSetting.xhr();
if(myXhr.upload) {
myXhr.upload.addEventListener('progress', function(e) {
var loaded = e.loaded; // 已经上传大小情况
var tot = e.total; // 附件总大小
var per = Math.floor(100 * loaded / tot).toFixed(2);
$('#progress').html(per + '%'); // 设置进度显示百分比
$('#progress').css('width', per + '%');
}, false)
} else {
return myXhr;
}
},
success: function(data) {
console.log(data);
console.log('上传成功!!!')
},
error: function() {
console.log('上传失败')
}
})
# axios获取上传进度
在axios中提供了一个参数onUploadProgress,有了这个参数就可以很方便的获取上传进度了,其方法实现还是和原生JS的一样,这个参数其实就是注册一个监听事件
var fd = new FormData();
fd.append('file', document.getElementById('testFile').files[0]);
axios({
method: 'post',
url: 'http://127.0.0.1:3003/useasync/uploadFile',
data: fd,
onUploadProgress: this.uploadProgress,
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err)
})
uploadProgress(evt) {
if(evt.lengthComputable) {
var percent = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progress').innerHTML = percent.toFixed(2) + '%';//设置进度显示百分比
document.getElementById('progress').style.width = percent.toFixed(2) + '%';//设置完成的进度条宽度
} else {
document.getElementById('progress').innerHTML = 'unable to compute'
}
}
如此,三种实现异步上传文件的进度条方法已经说完了,至于页面显示上其实就是两个div嵌套了,id为progress的进度,不断改变宽度,直至100%。
js文件异步上传进度条 (opens new window)
# 下载
# GET接口返回流文件内容前端需要自定义名字
aysnc download() {
const blodFile = await downloadAjax('/v1/file?fileType=0');
const a = document.createElement('a');
a.download = 'logs.tar.gz';
a.href = blodFile;
a.click();
}
# 如果使用post请求下载文件流
- 接口
接口地址: /file/download/${id}
前端请求这里要注意(重点)设置responseType: 'blob'.
import {axios} from '../../config';
import {BaseURL} from '@/serviceConfig';
// 附件下载
export const download = id => axios({
method:'post',
url: `${BaseURL}/file/download/${id}`,
responseType: 'blob'
})
然后请求回来的结果是blob
async downloadDoc(id) {
let res = await download(id);
let blob = res.data;
let url = window.URL.createObjectURL(blob);
let elelink = document.createElement('a');
elelink.href = url;
elelink.download = name;
document.boduy.appendClild(elelink);
elelink.click();
window.URL.revokeObjectURL(url);
}
- 拓展
不常用的方法:window.URL.createObjectURL(blob) 和window.URL.revokeObjectURL(url).
window.URL.createObjectURL(blob);
每次你调用window.URL.createObjectURL(),就会长生一个唯一的对象URL
blob:http://xxxxx<文件地址>
获得这个地址之后,就会开启下载任务
window.URL.revokeObjectUrl(url);
当文档关闭时,他们会自动被释放。如果你的网页要动态使用他们,你需要显式调用window.URL.revokeObjectURL()来释放他们。
# fetch
其实fetch也可以流上传 参考下面 前端流式传输播放音视频
# FormData
FormData 是 HTML5 新增的一个对象,它可以用于将表单数据以键值对的形式存储在内存中,并且可以通过 XMLHttpRequest 对象发送到服务器。
FormData 提供了以下方法:
- append(name, value):向 FormData 对象中添加一个键值对。
- delete(name):从 FormData 对象中删除指定的键值对。
- get(name):获取 FormData 对象中指定键的值。
- has(name):判断 FormData 对象中是否存在指定的键。
- set(name, value):设置 FormData 对象中指定键的值。
- forEach(callback):遍历 FormData 对象中的每个键值对,并执行回调函数。
- entries():返回一个迭代器,用于遍历 FormData 对象中的每个键值对。
- keys():返回一个迭代器,用于遍历 FormData 对象中的每个键。
- values():返回一个迭代器,用于遍历 FormData 对象中的每个值。
# 一、给 FormData 对象添加数据
const formData = new FormData();
formData.append('name', 'John');
formData.append('age', '30');
formData.append('file', fileInput); // fileInput 是File类型
# 二、取出 FormData中的值
遍历所有字段(最通用)
for(const [key, value] of formData.entries()) { console.log(key, value); }获取指定字段的值
const name = formData.get('name'); const age = formData.get('age');获取所有某字段的值(同名字段情况)
const files = formData.getAll('file');判断某字段是否存在
formData.has('age');