火宫殿烧鹅 發表於 2020-5-5 14:47:00

JavaScript 实现前端文件下载

<h2 id="h2_1">A.download</h2>
<p>HTML5的A标签有一个<code>download</code>属性,可以告诉浏览器下载而非预览文件,很实用,参考链接:http://www.zhangxinxu.com/wordpress/2016/04/know-about-html-download-attribute/</p>
<p>有时候,WEB端临时创建了一个文件,供用户下载,怎么办呢?示例如下:</p>
<pre><code class="hljs javascript"><span class="hljs-comment">// 从canvas提取图片数据
<span class="hljs-keyword">var raw = ctx.getImageData(<span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-number">300, <span class="hljs-number">300);
<span class="hljs-comment">// 压缩为JPEG图片
<span class="hljs-comment">// https://github.com/owencm/javascript-jpeg-encoder
<span class="hljs-keyword">var jpegURI = (<span class="hljs-keyword">new JPEGEncoder()).encode(raw, <span class="hljs-number">75);
<span class="hljs-comment">// 弹出对话框,交由用户保存图片
saveFile(jpegURI, <span class="hljs-string">'文件名');

<span class="hljs-comment">// saveFile函数
<span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">saveFile(<span class="hljs-params">d, a) {
    <span class="hljs-keyword">var b = <span class="hljs-built_in">document.createElement(<span class="hljs-string">'a');
    b.href = d;
    b.download = a;
    <span class="hljs-keyword">var c = <span class="hljs-built_in">document.createEvent(<span class="hljs-string">"MouseEvents");
    c.initMouseEvent(<span class="hljs-string">"click", <span class="hljs-literal">true, <span class="hljs-literal">false, <span class="hljs-built_in">window, <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-number">0, <span class="hljs-literal">false, <span class="hljs-literal">false, <span class="hljs-literal">false, <span class="hljs-literal">false, <span class="hljs-number">0, <span class="hljs-literal">null);
    b.dispatchEvent(c);
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code><br><br></pre>
<h2 id="h2_2">FileSaver.js</h2>
<p>这是另一种方案,效果也不错。这里推荐FileSaver.js</p>
<p>https://github.com/ChenWenBrian/FileSaver.js</p>
<p>调用方法:</p>
<p>var blob = new Blob(, {type: "text/plain;charset=utf-8"});</p>
<p>saveAs(blob, "content.csv");</p>
<p>这里还有一段原作者的博文。</p>
<p>最后,贴出JS便于查看:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> FileSaver.js
* A saveAs() FileSaver implementation.
* 1.1.20151003
*
* By Eli Grey, http://eligrey.com
* License: MIT
*   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>

<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">global self </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true </span><span style="color: rgba(0, 128, 0, 1)">*/</span>

<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js </span><span style="color: rgba(0, 128, 0, 1)">*/</span>

<span style="color: rgba(0, 0, 255, 1)">var</span> saveAs = saveAs || (<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(view) {
    </span>"use strict"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> IE &lt;10 is explicitly unsupported</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> navigator !== "undefined" &amp;&amp; /MSIE \./<span style="color: rgba(0, 0, 0, 1)">.test(navigator.userAgent)) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
          doc </span>=<span style="color: rgba(0, 0, 0, 1)"> view.document
          </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> only get URL when necessary in case Blob.js hasn't overridden it yet</span>
      , get_URL = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> view.URL || view.webkitURL ||<span style="color: rgba(0, 0, 0, 1)"> view;
      }
      , save_link </span>= doc.createElementNS("http://www.w3.org/1999/xhtml", "a"<span style="color: rgba(0, 0, 0, 1)">)
      , can_use_save_link </span>= "download" <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> save_link
      , click </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(node) {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> event = <span style="color: rgba(0, 0, 255, 1)">new</span> MouseEvent("click"<span style="color: rgba(0, 0, 0, 1)">);
            node.dispatchEvent(event);
      }
      , is_safari </span>= /Version\/[\d\.]+.*Safari/<span style="color: rgba(0, 0, 0, 1)">.test(navigator.userAgent)
      , webkit_req_fs </span>=<span style="color: rgba(0, 0, 0, 1)"> view.webkitRequestFileSystem
      , req_fs </span>= view.requestFileSystem || webkit_req_fs ||<span style="color: rgba(0, 0, 0, 1)"> view.mozRequestFileSystem
      , throw_outside </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(ex) {
            (view.setImmediate </span>|| view.setTimeout)(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> ex;
            }, </span>0<span style="color: rgba(0, 0, 0, 1)">);
      }
      , force_saveable_type </span>= "application/octet-stream"<span style="color: rgba(0, 0, 0, 1)">
      , fs_min_size </span>= 0
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047</span>
      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> for the reasoning behind the timeout and revocation flow</span>
      , arbitrary_revoke_timeout = 500 <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> in ms</span>
      , revoke = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(file) {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> revoker = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> file === "string") { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> file is an object URL</span>
<span style="color: rgba(0, 0, 0, 1)">                  get_URL().revokeObjectURL(file);
                } </span><span style="color: rgba(0, 0, 255, 1)">else</span> { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> file is a File</span>
<span style="color: rgba(0, 0, 0, 1)">                  file.remove();
                }
            };
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (view.chrome) {
                revoker();
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                setTimeout(revoker, arbitrary_revoke_timeout);
            }
      }
      , dispatch </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(filesaver, event_types, event) {
            event_types </span>=<span style="color: rgba(0, 0, 0, 1)"> [].concat(event_types);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> i =<span style="color: rgba(0, 0, 0, 1)"> event_types.length;
            </span><span style="color: rgba(0, 0, 255, 1)">while</span> (i--<span style="color: rgba(0, 0, 0, 1)">) {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> listener = filesaver["on" +<span style="color: rgba(0, 0, 0, 1)"> event_types];
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> listener === "function"<span style="color: rgba(0, 0, 0, 1)">) {
                  </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                        listener.call(filesaver, event </span>||<span style="color: rgba(0, 0, 0, 1)"> filesaver);
                  } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (ex) {
                        throw_outside(ex);
                  }
                }
            }
      }
      , auto_bom </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(blob) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> prepend BOM for UTF-8 XML and text/* types (including HTML)</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span> (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/<span style="color: rgba(0, 0, 0, 1)">i.test(blob.type)) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Blob(["\ufeff"<span style="color: rgba(0, 0, 0, 1)">, blob], {type: blob.type});
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> blob;
      }
      , FileSaver </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(blob, name, no_auto_bom) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">no_auto_bom) {
                blob </span>=<span style="color: rgba(0, 0, 0, 1)"> auto_bom(blob);
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> First try a.download, then web filesystem, then object URLs</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
                  filesaver </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">
                , type </span>=<span style="color: rgba(0, 0, 0, 1)"> blob.type
                , blob_changed </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
                , object_url
                , target_view
                , dispatch_all </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                  dispatch(filesaver, </span>"writestart progress write writeend".split(" "<span style="color: rgba(0, 0, 0, 1)">));
                }
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> on any filesys errors revert to saving with object URLs</span>
                , fs_error = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (target_view &amp;&amp; is_safari &amp;&amp; <span style="color: rgba(0, 0, 255, 1)">typeof</span> FileReader !== "undefined"<span style="color: rgba(0, 0, 0, 1)">) {
                        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Safari doesn't allow downloading of blob urls</span>
                        <span style="color: rgba(0, 0, 255, 1)">var</span> reader = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FileReader();
                        reader.onloadend </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                            </span><span style="color: rgba(0, 0, 255, 1)">var</span> base64Data =<span style="color: rgba(0, 0, 0, 1)"> reader.result;
                            target_view.location.href </span>= "data:attachment/file" + base64Data.slice(base64Data.search(/[,;]/<span style="color: rgba(0, 0, 0, 1)">));
                            filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE;
                            dispatch_all();
                        };
                        reader.readAsDataURL(blob);
                        filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.INIT;
                        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
                  }
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> don't create more object URLs than needed</span>
                  <span style="color: rgba(0, 0, 255, 1)">if</span> (blob_changed || !<span style="color: rgba(0, 0, 0, 1)">object_url) {
                        object_url </span>=<span style="color: rgba(0, 0, 0, 1)"> get_URL().createObjectURL(blob);
                  }
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (target_view) {
                        target_view.location.href </span>=<span style="color: rgba(0, 0, 0, 1)"> object_url;
                  } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                        </span><span style="color: rgba(0, 0, 255, 1)">var</span> new_tab = view.open(object_url, "_blank"<span style="color: rgba(0, 0, 0, 1)">);
                        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (new_tab == undefined &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> is_safari) {
                            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Apple do not allow window.open, see http://bit.ly/1kZffRI</span>
                            view.location.href =<span style="color: rgba(0, 0, 0, 1)"> object_url
                        }
                  }
                  filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE;
                  dispatch_all();
                  revoke(object_url);
                }
                , abortable </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(func) {
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (filesaver.readyState !==<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE) {
                            </span><span style="color: rgba(0, 0, 255, 1)">return</span> func.apply(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, arguments);
                        }
                  };
                }
                , create_if_not_found </span>= {create: <span style="color: rgba(0, 0, 255, 1)">true</span>, exclusive: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">}
                , slice
            ;
            filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.INIT;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">name) {
                name </span>= "download"<span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (can_use_save_link) {
                object_url </span>=<span style="color: rgba(0, 0, 0, 1)"> get_URL().createObjectURL(blob);
                save_link.href </span>=<span style="color: rgba(0, 0, 0, 1)"> object_url;
                save_link.download </span>=<span style="color: rgba(0, 0, 0, 1)"> name;
                setTimeout(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                  click(save_link);
                  dispatch_all();
                  revoke(object_url);
                  filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE;
                });
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Object and web filesystem URLs have a problem saving in Google Chrome when</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> viewed in a tab, so I force save with application/octet-stream</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> http://code.google.com/p/chromium/issues/detail?id=91158</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Update: Google errantly closed 91158, I submitted it again:</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> https://code.google.com/p/chromium/issues/detail?id=389642</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span> (view.chrome &amp;&amp; type &amp;&amp; type !==<span style="color: rgba(0, 0, 0, 1)"> force_saveable_type) {
                slice </span>= blob.slice ||<span style="color: rgba(0, 0, 0, 1)"> blob.webkitSlice;
                blob </span>= slice.call(blob, 0<span style="color: rgba(0, 0, 0, 1)">, blob.size, force_saveable_type);
                blob_changed </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Since I can't be sure that the guessed media type will trigger a download</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> in WebKit, I append .download to the filename.</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> https://bugs.webkit.org/show_bug.cgi?id=65440</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span> (webkit_req_fs &amp;&amp; name !== "download"<span style="color: rgba(0, 0, 0, 1)">) {
                name </span>+= ".download"<span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (type === force_saveable_type ||<span style="color: rgba(0, 0, 0, 1)"> webkit_req_fs) {
                target_view </span>=<span style="color: rgba(0, 0, 0, 1)"> view;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">req_fs) {
                fs_error();
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            fs_min_size </span>+=<span style="color: rgba(0, 0, 0, 1)"> blob.size;
            req_fs(view.TEMPORARY, fs_min_size, abortable(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(fs) {
                fs.root.getDirectory(</span>"saved", create_if_not_found, abortable(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(dir) {
                  </span><span style="color: rgba(0, 0, 255, 1)">var</span> save = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                        dir.getFile(name, create_if_not_found, abortable(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(file) {
                            file.createWriter(abortable(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(writer) {
                              writer.onwriteend </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(event) {
                                    target_view.location.href </span>=<span style="color: rgba(0, 0, 0, 1)"> file.toURL();
                                    filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE;
                                    dispatch(filesaver, </span>"writeend"<span style="color: rgba(0, 0, 0, 1)">, event);
                                    revoke(file);
                              };
                              writer.onerror </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                                    </span><span style="color: rgba(0, 0, 255, 1)">var</span> error =<span style="color: rgba(0, 0, 0, 1)"> writer.error;
                                    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (error.code !==<span style="color: rgba(0, 0, 0, 1)"> error.ABORT_ERR) {
                                        fs_error();
                                    }
                              };
                              </span>"writestart progress write abort".split(" ").forEach(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(event) {
                                    writer[</span>"on" + event] = filesaver["on" +<span style="color: rgba(0, 0, 0, 1)"> event];
                              });
                              writer.write(blob);
                              filesaver.abort </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
                                    writer.abort();
                                    filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE;
                              };
                              filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.WRITING;
                            }), fs_error);
                        }), fs_error);
                  };
                  dir.getFile(name, {create: </span><span style="color: rgba(0, 0, 255, 1)">false</span>}, abortable(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(file) {
                        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> delete file if it already exists</span>
<span style="color: rgba(0, 0, 0, 1)">                        file.remove();
                        save();
                  }), abortable(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(ex) {
                        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (ex.code ===<span style="color: rgba(0, 0, 0, 1)"> ex.NOT_FOUND_ERR) {
                            save();
                        } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                            fs_error();
                        }
                  }));
                }), fs_error);
            }), fs_error);
      }
      , FS_proto </span>=<span style="color: rgba(0, 0, 0, 1)"> FileSaver.prototype
      , saveAs </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(blob, name, no_auto_bom) {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FileSaver(blob, name, no_auto_bom);
      }
    ;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> IE 10+ (native saveAs)</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> navigator !== "undefined" &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> navigator.msSaveOrOpenBlob) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(blob, name, no_auto_bom) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">no_auto_bom) {
                blob </span>=<span style="color: rgba(0, 0, 0, 1)"> auto_bom(blob);
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> navigator.msSaveOrOpenBlob(blob, name || "download"<span style="color: rgba(0, 0, 0, 1)">);
      };
    }

    FS_proto.abort </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> filesaver = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
      filesaver.readyState </span>=<span style="color: rgba(0, 0, 0, 1)"> filesaver.DONE;
      dispatch(filesaver, </span>"abort"<span style="color: rgba(0, 0, 0, 1)">);
    };
    FS_proto.readyState </span>= FS_proto.INIT = 0<span style="color: rgba(0, 0, 0, 1)">;
    FS_proto.WRITING </span>= 1<span style="color: rgba(0, 0, 0, 1)">;
    FS_proto.DONE </span>= 2<span style="color: rgba(0, 0, 0, 1)">;

    FS_proto.error </span>=<span style="color: rgba(0, 0, 0, 1)">
    FS_proto.onwritestart </span>=<span style="color: rgba(0, 0, 0, 1)">
    FS_proto.onprogress </span>=<span style="color: rgba(0, 0, 0, 1)">
    FS_proto.onwrite </span>=<span style="color: rgba(0, 0, 0, 1)">
    FS_proto.onabort </span>=<span style="color: rgba(0, 0, 0, 1)">
    FS_proto.onerror </span>=<span style="color: rgba(0, 0, 0, 1)">
    FS_proto.onwriteend </span>=
      <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> saveAs;
}(
       </span><span style="color: rgba(0, 0, 255, 1)">typeof</span> self !== "undefined" &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> self
    </span>|| <span style="color: rgba(0, 0, 255, 1)">typeof</span> window !== "undefined" &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> window
    </span>|| <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.content
));
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> `self` is undefined in Firefox for Android content script context</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> while `this` is nsIContentFrameMessageManager</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> with an attribute `content` that corresponds to the window</span>

<span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> module !== "undefined" &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> module.exports) {
module.exports.saveAs </span>=<span style="color: rgba(0, 0, 0, 1)"> saveAs;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> ((<span style="color: rgba(0, 0, 255, 1)">typeof</span> define !== "undefined" &amp;&amp; define !== <span style="color: rgba(0, 0, 255, 1)">null</span>) &amp;&amp; (define.amd != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)) {
define([], </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> saveAs;
});
}</span></pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/tiandi/p/12830733.html
頁: [1]
查看完整版本: JavaScript 实现前端文件下载