关于ajax无刷新上传和下载
关于 ajax 无刷新上传和下载
这是一个没什么含量但是又用的比较多又不得不说的问题,其实真的不想说,因为没什么好说的。
关于上传
使用 Flash, ActiveX 上传 ,略...
自己写 XMLHttpRequest
// 准备FormData
var formData = new FormData();
formData.append("key", value);
// 创建xhr对象
var xhr = new XMLHttpRequest();
// 监听状态,实时响应
// xhr 和 xhr.upload 都有progress事件,xhr.progress是下载进度,xhr.upload.progress是上传进度
xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
var percent = Math.round(event.loaded / event.total);
console.log("%d%", percent);
}
};
// 传输开始事件
xhr.onloadstart = function (event) {
console.log("load start");
};
// ajax过程成功完成事件
xhr.onload = function (event) {
console.log("load success");
console.log(xhr.responseText);
var ret = JSON.parse(xhr.responseText);
console.log(ret);
};
// ajax过程发生错误事件
xhr.onerror = function (event) {
console.log("error");
};
// ajax被取消
xhr.onabort = function (event) {
console.log("abort");
};
// loadend传输结束,不管成功失败都会被触发
xhr.onloadend = function (event) {
console.log("load end");
};
// 发起ajax请求传送数据
xhr.open("POST", "/upload", true);
xhr.send(formData);
使用 Jquery
var formData = new FormData();
formData.append("key", value); //传的参和值
$.ajax({
url: "XXX",
type: "POST",
data: formData,
contentType: false,
processData: false,
success: function (res) {},
error: function () {},
});
这里要说的就是 formData
,这个狗屎在 IE10
之后才开始完整的支持,IE9 吖的是个半残品。所以这要说的是第三种结合 form
和 iframe
来实现,原理:
隐藏的 form
和 iframe
, form
的 target
指向 iframe
,监听 iframe load
,来获取上传结果。
优点:兼容该死的 ie 低版本浏览器
缺点:跨域上传不支持,还需自定义反向代理,因为 iframe onload
不支持跨域
上传接口 API: 成功返回:
{
code: 1,
msg: '上传成功'
}
失败返回:
{
code: 0,
msg: '上传失败'
}
HTML:
<form
action="xxxx"
target="upload"
enctype="multipart/form-data"
method="post"
style="display:none; "
>
... ..
</form>
<iframe name="upload" id="upload"></iframe>
<!-- JS: -->
<script>
var fm = document.getElementById("upload");
var load = function () {
var doc = fm.contentWindow || fm.contentDocument;
if (doc.document) doc = doc.document;
var content = doc.body.textContent; //此处的值取决与API 接口返回的值
var data = JSON.parse(content);
console.log(content);
};
// 兼容低版本浏览器监听判断
fm.attachEvent ? fm.attachEvent("onload", load) : (fm.onload = load);
</script>
关于下载:
暴力一点的下载直接
window.open("/rest/donwload/abcd.do");
优点:代码量少。
缺点:现代浏览器会自动识别文件类型,如 pdf,会自动在浏览器打开
优雅一点的下载:
function download() {
var a = document.createElement("a");
var url = "download/?filename=aaa.txt";
var filename = "data.xlsx";
a.href = url;
a.download = filename;
a.click();
}
优点:解决了暴力下载自动打开文件的缺陷
缺点:不支持 post 方式下载
使用 XMLHttpRequest,BLOB 方式
function download() {
var url = "download/?filename=aaa.txt";
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement("a");
a.download = "data.xlsx";
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
};
}
};
// 发送ajax请求
xhr.send();
}
优点:支持 post 方式
缺点:还是该死的兼容性问题
所以处理兼容性最好的方式 还是 form
结合 iframe
(不考虑兼容性当然还是 XMLHttpRequest
最好) ,这种方式不论是上传和下载 都是完美支持的。上传下载通用。
最好的上传下载方式: 你们的 Boss 不要求兼容 ie 低版本浏览器
[完]