/ * F i l e S a v e r . j s
* A saveAs ( ) FileSaver implementation .
* 1.3 . 2
* 2016 - 06 - 16 18 : 25 : 19
*
* By Eli Grey , http : //eligrey.com
* 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 )
, 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 ;
} ) ;
}