首先介绍一下用到的基本知识
formdata
MDN上的定义:FormData 接口提供了一种表示表单数据的键值对的构造方式,经过它的数据可以使用 XMLHttpRequest.send() 方法送出。
简单说就是用来构造http请求的参数(可以携带文件数据)。
常用方法:FormData(form)
构造函数,参数可选,为一个form对象Dom,会包含进该form的值FormData.append(key,value)
用于添加新的属性值,即使原属性存在也不会覆蓋,而是新增键值对formdata.delete(key)
用于删除对象键值对
示例
html代码
<form id="myForm" name="myForm">
<div>
<label for="username">Enter name:</label>
<input type="text" id="username" name="username">
</div>
<div>
<label for="useracc">Enter account number:</label>
<input type="text" id="useracc" name="useracc">
</div>
<div>
<label for="userfile">Upload file:</label>
<input type="file" id="userfile" name="userfile">
</div>
<input type="submit" value="Submit!">
</form>
js代码
let form = document.getElementById('myForm');
let mrFormData = new FormData(form);
mrFormData.append('key1','value1');
mrFormData.append('key2','value2');
Blob
Blob是一个js用于构造流类型数据的对象
构造函数用法:var aBlob = new Blob( array, options );
其中array是二进制数据,字符串数据等组成的数组
options是一个可选的BlobPropertyBag字典,
示例
let aFileParts = ['<a id="a"><b id="b">hey!</b></a>']; // 一个包含DOMString的数组
let oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
有了这两个对象,就可以开始分步骤实现文件上传和下载了
1.生成一个formdata对象,用于向服务端传递数据
var mrFormData = new FormData();
mrFormData.append("upload-type", "TYPE_MERGE");
mrFormData.append("upload-name", 'XXXX');
mrFormData.append("upload-total", 'XXXX');
mrFormData.append("upload-index", 'XXXX');
2.构造ajax的post请求
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var result = xmlhttp.response;
var header = xmlhttp.getResponseHeader("content-disposition");
var fileName = getValueByStr('filename',header);
transArray2Csv(result,fileName);//生成csv
}
}
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("X-Uni-Crsf-Token", (top.session && top.session.csrfToken) || "");
xmlhttp.responseType = "text";
xmlhttp.send(mrFormData);//向服务器发送数据
3.处理返回数据生成CSV并下载
function transArray2Csv(result, filename) {
var blob = new Blob([result], {
type: "text/plain"
})
const link = document.createElement("a")
link.href = URL.createObjectURL(blob)
link.download = filename // 这里填保存成的文件名
link.click()
URL.revokeObjectURL(link.href)
}
至此,下载完成
注意事项(开发过程中遇到的问题)
- jq的ajax函数不支持返回流数据的处理,需要自己写一个ajax请求;
- ajax进行post请求并发送数据时,需要在头部添加content-type,
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
; - 当发送数据为formdata数据时,浏览器会自动识别并添加头
content-type:multipart/form-data
,并添加一个随机字符串boundary用于分割formdata的每个属性,且后台基于此解析formdata; - 若没有上传数据,采用get请求下载文件最佳;
- js生成文件并下载时,若有一个可以直接用于文件下载的接口,可以通过执行
window.location.href = url
下载文件,浏览器不会刷新,否则采用例子中的标签方式下载。