前端js实现字符串/图片/excel文件下载

栏目: JavaScript · 发布时间: 5年前

内容简介:在传统的做法是在后端存储或者即时生成一个文件来提供下载功能,这样的优势是可以做权限控制、数据二次处理,但缺点是需要额外发起请求、增大服务端压力、下载速度慢。但随着

web 开发中,如果你想让用户下载或者导出一个文件,应该怎么做呢?

传统的做法是在后端存储或者即时生成一个文件来提供下载功能,这样的优势是可以做权限控制、数据二次处理,但缺点是需要额外发起请求、增大服务端压力、下载速度慢。

但随着 HTML5 的标准发布,我们已经能够做到只前端来下载各种文件了。

<a> 标签的 download 属性

此属性指示浏览器下载 URL 而不是导航到它,因此将提示用户将其保存为本地文件。如果属性有一个值,那么它将作为下载的文件名使用。此属性对允许的值没有限制,但是 /\ 会被转换为下划线。

  1. 此属性仅适用于同源 URLs
  2. 尽管 HTTP URL 需要位于同一源中,但是可以使用 blob: URLsdata: URLs ,以方便用户下载 JavaScript 方式生成的内容(例如使用在线绘图的 Web 应用创建的照片)。

常规的 <a> 标签,用于链接的跳转,如新的页面,那么如果我们给 <a> 标签加上 download 属性,就能很简单的让用户保存新的 html 页面。

<a download="PHP实现并发请求.html" href="https://segmentfault.com/a/1190000016343861">PHP实现并发请求</a>

生成并下载字符串文件

首先我们需要了解一个特殊的数据格式: Blob

Blob 数据

Blob(Binary Large Object,二进制类型的大对象) ,表示一个不可变的原始数据的类文件对象,我们上传文件时常用的 File 对象就继承于 Blob ,并进行了扩展用于支持用户系统上的文件。

我们只能通过 Blob() 构造函数来创建一个新的 Blob 对象:

Blob(blobParts[, options])

// 创建一个json类型的Blob对象,支持传入同类型数据的一个数组
var debug = {hello: "world"};
var blob = new Blob([JSON.stringify(debug, null, 2)],
  {type : 'application/json'});

// 此时blob的值
// Blob(22) {size: 22, type: 'application/json'}

Blob 对象存在两个只读属性:

size : Blob 对象中所包含数据的大小(字节)。

type : 一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。

URL 对象和下载字符串文件

URL 接口是一个用来创建 URLs 的对象,包含两个静态方法:

objectURL = URL.createObjectURL(blob)
创建一个 URL(DOMString) ,包含一个唯一的blob链接(该链接协议为以blob:,后跟唯一标识浏览器中的对象的掩码)。这个 URL 的生命周期和创建它的窗口中的 document 绑定。

URL.revokeObjectURL(objectURL)
销毁之前使用URL.createObjectURL()方法创建的URL实例。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。

var url = URL.createObjectURL(blob);
// 此时url的值,跟document绑定,所以每个页面创建的字符串均不同
// blob:https://developer.mozilla.org/defe53c2-2882-43c6-b275-db2a57959789

此时,我们在页面中创建一个新 <a> 标签,点击即可下载我们想要的文件:

<a href="blob:https://developer.mozilla.org/58702010-433d-4097-990f-e483d84cd02a" download="file.json">下载文件链接</a>

FileReader 读取 Blob 数据

想要读取 Blob 数据的唯一方法是 FileReader

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob 对象指定要读取的文件或数据。

其中 File 对象可以是来自用户在一个 <input> 元素上选择文件后返回的 FileList 对象,也可以来自拖放操作生成的 DataTransfer 对象,还可以是来自在一个 HTMLCanvasElement 上执行 mozGetAsFile() 方法后返回结果。

该对象包含3个属性:

FileReader.error
一个DOMException,表示在读取文件时发生的错误 。

FileReader.readyState
表示FileReader状态的数字。取值如下:

常量名    值    描述
EMPTY    0    还没有加载任何数据.
LOADING    1    数据正在被加载.
DONE    2    已完成全部的读取请求.

FileReader.result
文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。

包含6个事件处理: onabort,onerror,onload,onloadstart,onloadend,onprogress ,这些不再详细说明,因为 FileReader 继承自 EventTarget ,所以所有这些事件也可以通过 addEventListener 方法使用。

包含5个方法:

FileReader.abort()
中止读取操作。在返回时,readyState属性为DONE。

FileReader.readAsArrayBuffer()
开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.

FileReader.readAsBinaryString()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。

FileReader.readAsDataURL()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。

FileReader.readAsText()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。

因此我们可以直接读取 Blob 对象的数据:

var reader = new FileReader();
reader.addEventListener("loadend", function() {
   console.log(reader.result);
});
reader.readAsDataURL(blob);
// 此时result的值
// data:application/json;base64,ewogICJoZWxsbyI6ICJ3b3JsZCIKfQ==
reader.readAsText(blob);
// 此时result的值
// {
//     "hello": "world"
// }

下载图片

除了下载手动生成的字符串或对象,我们还能提供下载图片的功能,一方面能用于支持 Canvas 绘图的保存功能,一方面能提供批量下载图片等高级功能。

除了浏览器自带的右键保存,我们还可以这么做来下载图片:

// 通过src获取图片的blob对象
function getImageBlob(url, cb) {
    var xhr = new XMLHttpRequest();
    xhr.open("get", url, true);
    xhr.responseType = "blob";
    xhr.onload = function() {
        if (this.status == 200) {
            cb(this.response);
        }
    };
    xhr.send();
}

let reader = new FileReader();
reader.addEventListener("loadend", function() {
   console.log(reader.result);
});
getImageBlob('https://cdn.segmentfault.com/v-5c4ec07f/global/img/user-64.png', function(blob){
    // 读取来看下下载的内容
    reader.readAsDataURL(blob);
    // 最终生成的字符串
    // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAA...
    // 生成下载用的URL对象
    let url = URL.createObjectURL(blob);
    // 生成一个a标签,并模拟点击,即可下载,批量下载同理
    let aDom = aDom = document.createElement('a');
    aDom.href = url;
    aDom.download = 'download.json';
    aDom.text = '下载文件';
    document.getElementsByTagName('body')[0].appendChild(aDom);
    aDom.click();
});

下载 excel 文件等

如果你明白了下载的原理,那么所有的内容都能够理解,只不过是转换成对应的格式而已,当然,复杂格式的文档不需要你自己去配置,可以引入第三方库,在 excel 文档方面我选择用 tableExport库

// 引入CDN文件
'https://cdn.bootcss.com/xlsx/0.14.1/xlsx.core.min.js',
'https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js',
'https://cdn.bootcss.com/TableExport/5.2.0/js/tableexport.min.js'

// 绑定下载事件,这个是我自己的场景下代码,可能不适合大家,具体的参考官方文档
const tableDom = $('#table');
$('.table-exportBtn', tableDom).on('click', function () {
    const tableExport = tableDom.tableExport({
        formats: ['xlsx', 'txt'],
        filename: '表格下载',
        exportButtons: false
    });
    const type = $(this).data().type;
    const exportData = tableExport.getExportData()[tableDom[0].id][type];
    const {data, mimeType, filename, fileExtension} = exportData;
    tableExport.export2file(data, mimeType, filename, fileExtension);
});

参考资料

  1. MDN-a: https://developer.mozilla.org...
  2. MDN-blob: https://developer.mozilla.org...
  3. 掘金-细说Web API中的Blob: https://juejin.im/post/59e35d...
  4. MDN-URL: https://developer.mozilla.org...
  5. MDN-FileReader: https://developer.mozilla.org...
  6. 博客园-js 获取图片url的Blob值并预览: https://www.cnblogs.com/tujia...
  7. tableExport文档: https://tableexport.v5.travis...

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Speed Up Your Site

Speed Up Your Site

Andrew B. King / New Riders Press / 2003-01-14 / USD 39.99

There's a time bomb on the web: user patience. It starts ticking each time someone opens one of your pages. You only have a few seconds to get compelling content onto the screen. Fail, and you can kis......一起来看看 《Speed Up Your Site》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具