前端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...

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

查看所有标签

猜你喜欢:

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

Dreamweaver CS3 Bible

Dreamweaver CS3 Bible

Joseph W. Lowery / Wiley / May 21, 2007 / $49.99

Book Description Learn to create dynamic, data-driven Web sites using the exciting enhancements in the Dreamweaver CS3 version. You get a thorough understanding of the basics and then progress to l......一起来看看 《Dreamweaver CS3 Bible》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换