基于formdata与blob的文件上传与下载

8次阅读

共计 2409 个字符,预计需要花费 7 分钟才能阅读完成。

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

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

至此,下载完成

注意事项(开发过程中遇到的问题)
  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 下载文件,浏览器不会刷新,否则采用例子中的标签方式下载。
正文完
 0