js基于FileSaver.js 浏览器导出Excel文件的示例


Posted in Javascript onAugust 15, 2017

本文介绍了js基于FileSaver.js 浏览器导出Excel文件,分享给大家,也给自己做个笔记

限制一:不同浏览器对 blob 对象有不同的限制

具体看看下面这个表格(出自FileSaver.js):

Browser Constructs as Filenames Max Blob Size Dependencies
Firefox 20+ Blob Yes 800 MiB None
Firefox data: URI No n/a Blob.js
Chrome Blob Yes 500 MiB None
Chrome for Android Blob Yes 500 MiB None
Edge Blob Yes ? None
IE 10+ Blob Yes 600 MiB None
Opera 15+ Blob Yes 500 MiB None
Opera data: URI No n/a Blob.js
Safari 6.1+* Blob No ? None
Safari data: URI No n/a Blob.js

限制二:构建完 blob 对象后才会转换成文件

这一点限制对小文件(几十kb)可能没什么影响,但对稍微大一点的文件影响就很大了。试想,用户要下载一个 100mb 的文件,如果他点击了下载按钮之后没看到下载提示的话,他肯定会继续按,等他按了几次之后还没看到下载提示时,他就会抱怨我们的网站,然后离开了。

然而事实上下载的的确确发生了,只是要等到下载完文件之后才能构建 blob 对象,再转化成文件。而且,用户再触发多几次下载就会造成一些资源上的浪费。

因此,如果是要下载大文件的话,还是推荐直接创建一个 <a> 标签拉~
写 html 也好,写 JavaScript 动态创建也好,用自己喜欢的方式去创建就好了。

FileSaver.js 

/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 1.3.2
 * 2016-06-16 18:25:19
 *
 * License: MIT
 *  See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
 */

/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs || (function(view) {
  "use strict";
  // IE <10 is explicitly unsupported
  if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
    return;
  }
  var
     doc = view.document
     // only get URL when necessary in case Blob.js hasn't overridden it yet
    , get_URL = function() {
      return view.URL || view.webkitURL || view;
    }
    , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
    , can_use_save_link = "download" in save_link
    , click = function(node) {
      var event = new MouseEvent("click");
      node.dispatchEvent(event);
    }
    , is_safari = /constructor/i.test(view.HTMLElement) || view.safari
    , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
    , throw_outside = function(ex) {
      (view.setImmediate || view.setTimeout)(function() {
        throw ex;
      }, 0);
    }
    , force_saveable_type = "application/octet-stream"
    // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
    , arbitrary_revoke_timeout = 1000 * 40 // in ms
    , revoke = function(file) {
      var revoker = function() {
        if (typeof file === "string") { // file is an object URL
          get_URL().revokeObjectURL(file);
        } else { // file is a File
          file.remove();
        }
      };
      setTimeout(revoker, arbitrary_revoke_timeout);
    }
    , dispatch = function(filesaver, event_types, event) {
      event_types = [].concat(event_types);
      var i = event_types.length;
      while (i--) {
        var listener = filesaver["on" + event_types[i]];
        if (typeof listener === "function") {
          try {
            listener.call(filesaver, event || filesaver);
          } catch (ex) {
            throw_outside(ex);
          }
        }
      }
    }
    , auto_bom = function(blob) {
      // prepend BOM for UTF-8 XML and text/* types (including HTML)
      // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
      if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
        return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
      }
      return blob;
    }
    , FileSaver = function(blob, name, no_auto_bom) {
      if (!no_auto_bom) {
        blob = auto_bom(blob);
      }
      // First try a.download, then web filesystem, then object URLs
      var
         filesaver = this
        , type = blob.type
        , force = type === force_saveable_type
        , object_url
        , dispatch_all = function() {
          dispatch(filesaver, "writestart progress write writeend".split(" "));
        }
        // on any filesys errors revert to saving with object URLs
        , fs_error = function() {
          if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
            // Safari doesn't allow downloading of blob urls
            var reader = new FileReader();
            reader.onloadend = function() {
              var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
              var popup = view.open(url, '_blank');
              if(!popup) view.location.href = url;
              url=undefined; // release reference before dispatching
              filesaver.readyState = filesaver.DONE;
              dispatch_all();
            };
            reader.readAsDataURL(blob);
            filesaver.readyState = filesaver.INIT;
            return;
          }
          // don't create more object URLs than needed
          if (!object_url) {
            object_url = get_URL().createObjectURL(blob);
          }
          if (force) {
            view.location.href = object_url;
          } else {
            var opened = view.open(object_url, "_blank");
            if (!opened) {
              // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
              view.location.href = object_url;
            }
          }
          filesaver.readyState = filesaver.DONE;
          dispatch_all();
          revoke(object_url);
        }
      ;
      filesaver.readyState = filesaver.INIT;

      if (can_use_save_link) {
        object_url = get_URL().createObjectURL(blob);
        setTimeout(function() {
          save_link.href = object_url;
          save_link.download = name;
          click(save_link);
          dispatch_all();
          revoke(object_url);
          filesaver.readyState = filesaver.DONE;
        });
        return;
      }

      fs_error();
    }
    , FS_proto = FileSaver.prototype
    , saveAs = function(blob, name, no_auto_bom) {
      return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
    }
  ;
  // IE 10+ (native saveAs)
  if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
    return function(blob, name, no_auto_bom) {
      name = name || blob.name || "download";

      if (!no_auto_bom) {
        blob = auto_bom(blob);
      }
      return navigator.msSaveOrOpenBlob(blob, name);
    };
  }

  FS_proto.abort = function(){};
  FS_proto.readyState = FS_proto.INIT = 0;
  FS_proto.WRITING = 1;
  FS_proto.DONE = 2;

  FS_proto.error =
  FS_proto.onwritestart =
  FS_proto.onprogress =
  FS_proto.onwrite =
  FS_proto.onabort =
  FS_proto.onerror =
  FS_proto.onwriteend =
    null;

  return saveAs;
}(
    typeof self !== "undefined" && self
  || typeof window !== "undefined" && window
  || this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== "undefined" && module.exports) {
 module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
 define("FileSaver.js", function() {
  return saveAs;
 });
}

调用方法

function expToExcel(){
      var content = $("#report").html();
      var blob = new Blob(["Hello, world!"], { type: "text/plain;charset=utf-8" });
      saveAs(blob, "hello world.txt");      
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
关于Ext中form移除textfield方法:hide(),setVisible(false),remove()
Dec 02 Javascript
JS实现的论坛Ajax打分效果完整实例
Oct 31 Javascript
Bootstrap多级导航栏(级联导航)的实现代码
Mar 08 Javascript
Bootstrap每天必学之按钮(Button)插件
Apr 25 Javascript
vue从使用到源码实现教程详解
Sep 19 Javascript
vue.js从安装到搭建过程详解
Mar 17 Javascript
JS实现页面内跳转的简单代码
Sep 03 Javascript
js用类封装pop弹窗组件
Oct 08 Javascript
详解vue + vuex + directives实现权限按钮的思路
Oct 24 Javascript
js点击时关闭该范围下拉菜单之外的菜单方法
Jan 11 Javascript
layui的table单击行勾选checkbox功能方法
Aug 14 Javascript
JavaScript直接调用函数与call调用的区别实例分析
May 22 Javascript
form表单序列化详解(推荐)
Aug 15 #Javascript
JavaScript上传文件时不用刷新页面方法总结(推荐)
Aug 15 #Javascript
JavaScript阻止表单提交方法(附代码)
Aug 15 #Javascript
jQuery DOM节点的遍历方法小结
Aug 15 #jQuery
Mongoose实现虚拟字段查询的方法详解
Aug 15 #Javascript
深入浅析Vue不同场景下组件间的数据交流
Aug 15 #Javascript
React应用中使用Bootstrap的方法
Aug 15 #Javascript
You might like
PHP 引用是个坏习惯
2010/03/12 PHP
ThinkPHP的SAE开发相关注意事项详解
2016/10/09 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
php使用json_decode后数字对象转换成了科学计数法的解决方法
2017/02/20 PHP
PHP实现的一致性Hash算法详解【分布式算法】
2018/03/31 PHP
js图片延迟技术一般的思路与示例
2014/03/20 Javascript
小结Node.js中非阻塞IO和事件循环
2014/09/18 Javascript
浅谈Javascript中深复制
2014/12/01 Javascript
JavaScript 对象深入学习总结(经典)
2015/09/29 Javascript
js实现C#的StringBuilder效果完整实例
2015/12/22 Javascript
浅谈js里面的InttoStr和StrtoInt
2016/06/14 Javascript
关于JavaScript中事件绑定的方法总结
2016/10/26 Javascript
jQuery实现导航高亮的方法【附demo源码下载】
2016/11/09 Javascript
浅谈jquery的html方法里包含特殊字符的处理
2016/11/30 Javascript
微信小程序之蓝牙的链接
2017/09/26 Javascript
JavaScript实现简单动态进度条效果
2018/04/06 Javascript
javascript实现蒙版与禁止页面滚动
2020/01/11 Javascript
JS常用正则表达式超全集(密码强度校验,金额校验,IE版本,IPv4,IPv6校验)
2020/02/03 Javascript
小程序点餐界面添加购物车左右摆动动画
2020/09/23 Javascript
解决Vue大括号字符换行踩的坑
2020/11/09 Javascript
VUE实现吸底按钮
2021/03/04 Vue.js
[19:26]TNC vs EG (BO3)
2018/06/07 DOTA
python和C语言混合编程实例
2014/06/04 Python
Linux RedHat下安装Python2.7开发环境
2017/05/20 Python
Python装饰器模式定义与用法分析
2018/08/06 Python
Python操作json的方法实例分析
2018/12/06 Python
细数nn.BCELoss与nn.CrossEntropyLoss的区别
2020/02/29 Python
学python需要去培训机构吗
2020/07/01 Python
Python爬虫之Selenium鼠标事件的实现
2020/12/04 Python
意大利在线眼镜精品店:Ottica Lipari
2019/11/11 全球购物
中职生自荐信
2013/10/13 职场文书
自荐信怎么写好
2013/11/11 职场文书
公诉意见书范文
2015/06/05 职场文书
给校长的建议书作文300字
2015/09/14 职场文书
《中国古代诗歌散文欣赏》高中语文教材
2019/08/20 职场文书
Java版 单机五子棋
2022/05/04 Java/Android