2

首先介绍一下用到的基本知识

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);
}

验证时发现,后台出现中文时,下载的csv出现了乱码,修改下载过程中的链接,不在用链接数据流实现下载:

link.href = 'data:text/csv;charset=utf8,\uFEFF'+encodeURI(result);

至此,下载完成

注意事项(开发过程中遇到的问题)
  1. jq的ajax函数不支持返回流数据的处理,需要自己写一个ajax请求;
  2. ajax进行post请求并发送数据时,需要在头部添加content-type, xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  3. 当发送数据为formdata数据时,浏览器会自动识别并添加头content-type:multipart/form-data,并添加一个随机字符串boundary用于分割formdata的每个属性,且后台基于此解析formdata;
  4. 若没有上传数据,采用get请求下载文件最佳;
  5. js生成文件并下载时,若有一个可以直接用于文件下载的接口,可以通过执行window.location.href = url下载文件,浏览器不会刷新,否则采用例子中的标签方式下载。

张磊
15 声望1 粉丝