首先介绍一下用到的基本知识
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
下载文件,浏览器不会刷新,否则采用例子中的标签方式下载。