html5-filesaver.js
Advanced tools
Comparing version 0.0.1 to 0.0.2
@@ -1,14 +0,2 @@ | ||
/*! FileSaver.js demo script | ||
* 2012-01-23 | ||
* | ||
* By Eli Grey, http://eligrey.com | ||
* License: X11/MIT | ||
* See LICENSE.md | ||
*/ | ||
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/demo/demo.js */ | ||
/*jshint laxbreak: true, laxcomma: true, smarttabs: true*/ | ||
/*global saveAs, self*/ | ||
(function(view) { | ||
@@ -15,0 +3,0 @@ "use strict"; |
576
FileSaver.js
@@ -1,257 +0,351 @@ | ||
/* FileSaver.js | ||
* A saveAs() FileSaver implementation. | ||
* 2015-07-02 | ||
* | ||
* By Eli Grey, http://eligrey.com | ||
* License: X11/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 */ | ||
(function (root, factory) { | ||
'use strict'; | ||
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ | ||
(function (root, factory) { | ||
if (typeof define === 'function' && define.amd) { | ||
define([], factory); | ||
} else if (typeof exports === 'object') { | ||
module.exports = factory; | ||
define([], function () { return factory(root); }); | ||
} else { | ||
root.saveAs = root.saveAs || factory(); | ||
root.saveAs = root.saveAs || factory(root); | ||
} | ||
})(this, (function (undefined) { | ||
return function() { | ||
"use strict"; | ||
var saveAs = (function(view) { | ||
// IE <10 is explicitly unsupported | ||
if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { | ||
return; | ||
})(this, function saveAsFactory(root, undefined) { | ||
'use strict'; | ||
if (root.navigator !== undefined) { | ||
/* | ||
* IE <10 is explicitly unsupported | ||
*/ | ||
if (/MSIE [1-9]\./.test(root.navigator.userAgent)) { | ||
return; | ||
} | ||
/* | ||
* IE 10+ (native saveAs) | ||
*/ | ||
if (root.navigator.msSaveOrOpenBlob) { | ||
return nativeIeSaveAs; | ||
} | ||
} | ||
function nativeIeSaveAs(blob, name) { | ||
return root.navigator.msSaveOrOpenBlob(autoBom(blob), name); | ||
} | ||
// `self` is undefined in Firefox for Android content script context | ||
// while `this` is nsIContentFrameMessageManager | ||
// with an attribute `content` that corresponds to the window | ||
var view = root.self || root.window || root.content; | ||
var saveLinkElement = view.document.createElementNS('http://www.w3.org/1999/xhtml', 'a'); | ||
var canUseSaveLink = 'download' in saveLinkElement; | ||
var webkitReqFs = view.webkitRequestFileSystem; | ||
var reqFs = view.requestFileSystem || webkitReqFs || view.mozRequestFileSystem; | ||
var forceSaveableType = 'application/octet-stream'; | ||
var fsMinSize = 0; | ||
// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and | ||
// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 | ||
// for the reasoning behind the timeout and revocation flow | ||
var arbitraryRevokeTimeout = 500; | ||
var setImmediate = view.setImmediate || view.setTimeout; | ||
function saveAs(blob, name) { | ||
return new FileSaver(blob, name); | ||
} | ||
var FSProto = FileSaver.prototype; | ||
FSProto.abort = fileSaverAbort; | ||
FSProto.INIT = 0; | ||
FSProto.WRITING = 1; | ||
FSProto.DONE = 2; | ||
FSProto.readyState = FSProto.INIT; | ||
FSProto.error = null; | ||
FSProto.onwritestart = null; | ||
FSProto.onprogress = null; | ||
FSProto.onwrite = null; | ||
FSProto.onabort = null; | ||
FSProto.onerror = null; | ||
FSProto.onwriteend = null; | ||
function FileSaver(blob, name) { | ||
this.blob = blob = autoBom(blob); | ||
this.saveUsingObjectURLs = saveUsingObjectURLs; | ||
this.execSave = execSave; | ||
// First try a.download, then web filesystem, then object URLs | ||
var filesaver = this; | ||
var type = blob.type; | ||
var blobChanged = false; | ||
var objectUrl; | ||
var targetView; | ||
filesaver.readyState = filesaver.INIT; | ||
name = name || 'download'; | ||
if ( canUseSaveLink ) { | ||
return saveUsingLinkElement(); | ||
} | ||
fixChromeSaveableType(); | ||
fixWebKitDownload(); | ||
if ( ! reqFs ) { | ||
return saveUsingObjectURLs(); | ||
} | ||
return saveUsingFyleSystem(filesaver); | ||
//////////////// | ||
function saveUsingLinkElement() { | ||
objectUrl = getURL().createObjectURL(blob); | ||
saveLinkElement.href = objectUrl; | ||
saveLinkElement.download = name; | ||
setImmediate(function () { | ||
triggerClickOnSaveLink(); | ||
dispatchAll(filesaver); | ||
revoke(objectUrl); | ||
filesaver.readyState = filesaver.DONE; | ||
}, 0); | ||
} | ||
function fixChromeSaveableType() { | ||
/* | ||
* Object and web filesystem URLs have a problem saving in Google Chrome when | ||
* viewed in a tab, so I force save with application/octet-stream | ||
* http://code.google.com/p/chromium/issues/detail?id=91158 | ||
* Update: Google errantly closed 91158, I submitted it again: | ||
* https://code.google.com/p/chromium/issues/detail?id=389642 | ||
*/ | ||
if (view.chrome && type && type !== forceSaveableType) { | ||
var slice = blob.slice || blob.webkitSlice; | ||
blob = slice.call(blob, 0, blob.size, forceSaveableType); | ||
blobChanged = true; | ||
} | ||
} | ||
function fixWebKitDownload() { | ||
// Since I can't be sure that the guessed media type will trigger a download | ||
// in WebKit, I append .download to the filename. | ||
// https://bugs.webkit.org/show_bug.cgi?id=65440 | ||
if (webkitReqFs && name !== 'download') { | ||
name += '.download'; | ||
} | ||
if (type === forceSaveableType || webkitReqFs) { | ||
targetView = view; | ||
} | ||
} | ||
// on any filesys errors revert to saving with object URLs | ||
function saveUsingObjectURLs() { | ||
// don't create more object URLs than needed | ||
if (blobChanged || ! objectUrl) { | ||
objectUrl = getURL().createObjectURL(blob); | ||
} | ||
execSave(objectUrl); | ||
} | ||
function execSave(objectUrl, file, event) { | ||
if( targetView ) { | ||
targetView.location.href = objectUrl; | ||
} else { | ||
var newTab = view.open(objectUrl, '_blank'); | ||
if ( newTab === undefined ) { | ||
/* | ||
* Apple do not allow window.open | ||
* see http://bit.ly/1kZffRI | ||
*/ | ||
view.location.href = objectUrl; | ||
} | ||
} | ||
filesaver.readyState = filesaver.DONE; | ||
if( ! event ) { | ||
dispatchAll(filesaver); | ||
} else { | ||
dispatch(filesaver, 'writeend', event); | ||
} | ||
revoke(file || objectUrl); | ||
} | ||
} | ||
function fileSaverAbort() { | ||
var filesaver = this; | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, 'abort'); | ||
} | ||
// TODO apply dispatch to FileSaver prototype | ||
function dispatchAll(filesaver) { | ||
dispatch(filesaver, 'writestart progress write writeend'.split(' ')); | ||
} | ||
function dispatch(filesaver, eventTypes, event) { | ||
eventTypes = [].concat(eventTypes); | ||
var i = eventTypes.length; | ||
while (i--) { | ||
var listener = filesaver['on' + eventTypes[i]]; | ||
if (typeof listener === 'function') { | ||
try { | ||
listener.call(filesaver, event || filesaver); | ||
} catch (ex) { | ||
throwOutside(ex); | ||
} | ||
} | ||
} | ||
} | ||
function saveUsingFyleSystem(filesaver) { | ||
fsMinSize += filesaver.blob.size; | ||
var createIfNotFound = {create: true, exclusive: false}; | ||
reqFs(view.TEMPORARY, fsMinSize, abortable(getFyleSystem), filesaver.saveUsingObjectURLs); | ||
//////////// | ||
function getFyleSystem(fs) { | ||
fs.root.getDirectory('temp', createIfNotFound, abortable(getTempDirectory), filesaver.saveUsingObjectURLs); | ||
} | ||
function getTempDirectory(dir) { | ||
dir.getFile(name, { create: false }, abortable(getExistentFileForRemove), abortable(existentFileNotFound) ); | ||
///////////// | ||
function getExistentFileForRemove(file) { | ||
// delete file if it already exists | ||
file.remove(function() { | ||
save(); | ||
}); | ||
} | ||
function existentFileNotFound(ex) { | ||
if (ex.name === 'NotFoundError') { | ||
save(); | ||
} else { | ||
filesaver.saveUsingObjectURLs(); | ||
} | ||
} | ||
////////// | ||
function save() { | ||
dir.getFile(name, createIfNotFound, abortable(getFileForWrite), filesaver.saveUsingObjectURLs); | ||
} | ||
function getFileForWrite(file) { | ||
file.createWriter(abortable(createWriter), filesaver.saveUsingObjectURLs); | ||
//////// | ||
function createWriter(writer) { | ||
writer.onwriteend = onWriterEnd; | ||
writer.onerror = onError; | ||
bindEventsToWriter(); | ||
writer.write(blob); | ||
filesaver.abort = onAbort; | ||
filesaver.readyState = filesaver.WRITING; | ||
//////////// | ||
function onWriterEnd(event) { | ||
filesaver.execSave(file.toURL(), file, event); | ||
} | ||
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; | ||
function onError() { | ||
var error = writer.error; | ||
if (error.code !== error.ABORT_ERR) { | ||
filesaver.saveUsingObjectURLs(); | ||
} | ||
, 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); | ||
} | ||
, webkit_req_fs = view.webkitRequestFileSystem | ||
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem | ||
, throw_outside = function(ex) { | ||
(view.setImmediate || view.setTimeout)(function() { | ||
throw ex; | ||
}, 0); | ||
} | ||
, force_saveable_type = "application/octet-stream" | ||
, fs_min_size = 0 | ||
// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and | ||
// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 | ||
// for the reasoning behind the timeout and revocation flow | ||
, arbitrary_revoke_timeout = 500 // 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(); | ||
} | ||
}; | ||
if (view.chrome) { | ||
revoker(); | ||
} else { | ||
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) | ||
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { | ||
return new Blob(["\ufeff", blob], {type: blob.type}); | ||
} | ||
return blob; | ||
} | ||
, FileSaver = function(blob, name) { | ||
blob = auto_bom(blob); | ||
// First try a.download, then web filesystem, then object URLs | ||
var | ||
filesaver = this | ||
, type = blob.type | ||
, blob_changed = false | ||
, object_url | ||
, target_view | ||
, dispatch_all = function() { | ||
dispatch(filesaver, "writestart progress write writeend".split(" ")); | ||
} | ||
// on any filesys errors revert to saving with object URLs | ||
, fs_error = function() { | ||
// don't create more object URLs than needed | ||
if (blob_changed || !object_url) { | ||
object_url = get_URL().createObjectURL(blob); | ||
} | ||
if (target_view) { | ||
target_view.location.href = object_url; | ||
} else { | ||
var new_tab = view.open(object_url, "_blank"); | ||
if (new_tab == undefined && typeof safari !== "undefined") { | ||
//Apple do not allow window.open, see http://bit.ly/1kZffRI | ||
view.location.href = object_url | ||
} | ||
} | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch_all(); | ||
revoke(object_url); | ||
} | ||
, abortable = function(func) { | ||
return function() { | ||
if (filesaver.readyState !== filesaver.DONE) { | ||
return func.apply(this, arguments); | ||
} | ||
}; | ||
} | ||
, create_if_not_found = {create: true, exclusive: false} | ||
, slice | ||
; | ||
filesaver.readyState = filesaver.INIT; | ||
if (!name) { | ||
name = "download"; | ||
} | ||
if (can_use_save_link) { | ||
object_url = get_URL().createObjectURL(blob); | ||
save_link.href = object_url; | ||
save_link.download = name; | ||
setTimeout(function() { | ||
click(save_link); | ||
dispatch_all(); | ||
revoke(object_url); | ||
filesaver.readyState = filesaver.DONE; | ||
}, 0); | ||
return; | ||
} | ||
// Object and web filesystem URLs have a problem saving in Google Chrome when | ||
// viewed in a tab, so I force save with application/octet-stream | ||
// http://code.google.com/p/chromium/issues/detail?id=91158 | ||
// Update: Google errantly closed 91158, I submitted it again: | ||
// https://code.google.com/p/chromium/issues/detail?id=389642 | ||
if (view.chrome && type && type !== force_saveable_type) { | ||
slice = blob.slice || blob.webkitSlice; | ||
blob = slice.call(blob, 0, blob.size, force_saveable_type); | ||
blob_changed = true; | ||
} | ||
// Since I can't be sure that the guessed media type will trigger a download | ||
// in WebKit, I append .download to the filename. | ||
// https://bugs.webkit.org/show_bug.cgi?id=65440 | ||
if (webkit_req_fs && name !== "download") { | ||
name += ".download"; | ||
} | ||
if (type === force_saveable_type || webkit_req_fs) { | ||
target_view = view; | ||
} | ||
if (!req_fs) { | ||
fs_error(); | ||
return; | ||
} | ||
fs_min_size += blob.size; | ||
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { | ||
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { | ||
var save = function() { | ||
dir.getFile(name, create_if_not_found, abortable(function(file) { | ||
file.createWriter(abortable(function(writer) { | ||
writer.onwriteend = function(event) { | ||
target_view.location.href = file.toURL(); | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, "writeend", event); | ||
revoke(file); | ||
}; | ||
writer.onerror = function() { | ||
var error = writer.error; | ||
if (error.code !== error.ABORT_ERR) { | ||
fs_error(); | ||
} | ||
}; | ||
"writestart progress write abort".split(" ").forEach(function(event) { | ||
writer["on" + event] = filesaver["on" + event]; | ||
}); | ||
writer.write(blob); | ||
filesaver.abort = function() { | ||
writer.abort(); | ||
filesaver.readyState = filesaver.DONE; | ||
}; | ||
filesaver.readyState = filesaver.WRITING; | ||
}), fs_error); | ||
}), fs_error); | ||
}; | ||
dir.getFile(name, {create: false}, abortable(function(file) { | ||
// delete file if it already exists | ||
file.remove(); | ||
save(); | ||
}), abortable(function(ex) { | ||
if (ex.code === ex.NOT_FOUND_ERR) { | ||
save(); | ||
} else { | ||
fs_error(); | ||
} | ||
})); | ||
}), fs_error); | ||
}), fs_error); | ||
} | ||
, FS_proto = FileSaver.prototype | ||
, saveAs = function(blob, name) { | ||
return new FileSaver(blob, name); | ||
} | ||
; | ||
// IE 10+ (native saveAs) | ||
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { | ||
return function(blob, name) { | ||
return navigator.msSaveOrOpenBlob(auto_bom(blob), name); | ||
}; | ||
} | ||
FS_proto.abort = function() { | ||
var filesaver = this; | ||
function bindEventsToWriter() { | ||
'writestart progress write abort'.split(' ').forEach(function (event) { | ||
writer['on' + event] = filesaver['on' + event]; | ||
}); | ||
} | ||
function onAbort() { | ||
writer.abort(); | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, "abort"); | ||
}; | ||
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; | ||
function abortable(func) { | ||
return function () { | ||
if (filesaver.readyState !== filesaver.DONE) { | ||
return func.apply(this, arguments); | ||
} | ||
}; | ||
} | ||
} | ||
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 | ||
return saveAs; | ||
function autoBom(blob) { | ||
// prepend BOM for UTF-8 XML and text/* types (including HTML) | ||
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { | ||
return new Blob(['\ufeff', blob], {type: blob.type}); | ||
} | ||
})()); | ||
return blob; | ||
} | ||
// only get URL when necessary in case Blob.js hasn't overridden it yet | ||
function getURL() { | ||
return view.URL || view.webkitURL || view; | ||
} | ||
function revoke(file) { | ||
setTimeout(revoker, arbitraryRevokeTimeout); | ||
/////////// | ||
function revoker() { | ||
if (typeof file === 'string') { // file is an object URL | ||
getURL().revokeObjectURL(file); | ||
} else { // file is a File | ||
file.remove(function(){}); | ||
} | ||
} | ||
} | ||
function throwOutside(ex) { | ||
setImmediate(function () { | ||
throw ex; | ||
}, 0); | ||
} | ||
function triggerClickOnSaveLink() { | ||
var event = new MouseEvent('click'); | ||
saveLinkElement.dispatchEvent(event); | ||
} | ||
return saveAs; | ||
}); |
@@ -1,1 +0,1 @@ | ||
(function(root,factory){if(typeof define==="function"&&define.amd){define([],factory)}else if(typeof exports==="object"){module.exports=factory}else{root.saveAs=root.saveAs||factory()}})(this,function(undefined){return function(){"use strict";var saveAs=function(view){if(typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var doc=view.document,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)},webkit_req_fs=view.webkitRequestFileSystem,req_fs=view.requestFileSystem||webkit_req_fs||view.mozRequestFileSystem,throw_outside=function(ex){(view.setImmediate||view.setTimeout)(function(){throw ex},0)},force_saveable_type="application/octet-stream",fs_min_size=0,arbitrary_revoke_timeout=500,revoke=function(file){var revoker=function(){if(typeof file==="string"){get_URL().revokeObjectURL(file)}else{file.remove()}};if(view.chrome){revoker()}else{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){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)){return new Blob(["\ufeff",blob],{type:blob.type})}return blob},FileSaver=function(blob,name){blob=auto_bom(blob);var filesaver=this,type=blob.type,blob_changed=false,object_url,target_view,dispatch_all=function(){dispatch(filesaver,"writestart progress write writeend".split(" "))},fs_error=function(){if(blob_changed||!object_url){object_url=get_URL().createObjectURL(blob)}if(target_view){target_view.location.href=object_url}else{var new_tab=view.open(object_url,"_blank");if(new_tab==undefined&&typeof safari!=="undefined"){view.location.href=object_url}}filesaver.readyState=filesaver.DONE;dispatch_all();revoke(object_url)},abortable=function(func){return function(){if(filesaver.readyState!==filesaver.DONE){return func.apply(this,arguments)}}},create_if_not_found={create:true,exclusive:false},slice;filesaver.readyState=filesaver.INIT;if(!name){name="download"}if(can_use_save_link){object_url=get_URL().createObjectURL(blob);save_link.href=object_url;save_link.download=name;setTimeout(function(){click(save_link);dispatch_all();revoke(object_url);filesaver.readyState=filesaver.DONE},0);return}if(view.chrome&&type&&type!==force_saveable_type){slice=blob.slice||blob.webkitSlice;blob=slice.call(blob,0,blob.size,force_saveable_type);blob_changed=true}if(webkit_req_fs&&name!=="download"){name+=".download"}if(type===force_saveable_type||webkit_req_fs){target_view=view}if(!req_fs){fs_error();return}fs_min_size+=blob.size;req_fs(view.TEMPORARY,fs_min_size,abortable(function(fs){fs.root.getDirectory("saved",create_if_not_found,abortable(function(dir){var save=function(){dir.getFile(name,create_if_not_found,abortable(function(file){file.createWriter(abortable(function(writer){writer.onwriteend=function(event){target_view.location.href=file.toURL();filesaver.readyState=filesaver.DONE;dispatch(filesaver,"writeend",event);revoke(file)};writer.onerror=function(){var error=writer.error;if(error.code!==error.ABORT_ERR){fs_error()}};"writestart progress write abort".split(" ").forEach(function(event){writer["on"+event]=filesaver["on"+event]});writer.write(blob);filesaver.abort=function(){writer.abort();filesaver.readyState=filesaver.DONE};filesaver.readyState=filesaver.WRITING}),fs_error)}),fs_error)};dir.getFile(name,{create:false},abortable(function(file){file.remove();save()}),abortable(function(ex){if(ex.code===ex.NOT_FOUND_ERR){save()}else{fs_error()}}))}),fs_error)}),fs_error)},FS_proto=FileSaver.prototype,saveAs=function(blob,name){return new FileSaver(blob,name)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(blob,name){return navigator.msSaveOrOpenBlob(auto_bom(blob),name)}}FS_proto.abort=function(){var filesaver=this;filesaver.readyState=filesaver.DONE;dispatch(filesaver,"abort")};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);return saveAs}}()); | ||
(function(root,factory){'use strict';if(typeof define==='function'&&define.amd){define([],function(){return factory(root)})}else{root.saveAs=root.saveAs||factory(root)}})(this,function saveAsFactory(root,undefined){'use strict';if(root.navigator!==undefined){if(/MSIE [1-9]\./.test(root.navigator.userAgent)){return}if(root.navigator.msSaveOrOpenBlob){return nativeIeSaveAs}}function nativeIeSaveAs(blob,name){return root.navigator.msSaveOrOpenBlob(autoBom(blob),name)}var view=root.self||root.window||root.content;var saveLinkElement=view.document.createElementNS('http://www.w3.org/1999/xhtml','a');var canUseSaveLink='download'in saveLinkElement;var webkitReqFs=view.webkitRequestFileSystem;var reqFs=view.requestFileSystem||webkitReqFs||view.mozRequestFileSystem;var forceSaveableType='application/octet-stream';var fsMinSize=0;var arbitraryRevokeTimeout=500;var setImmediate=view.setImmediate||view.setTimeout;function saveAs(blob,name){return new FileSaver(blob,name)}var FSProto=FileSaver.prototype;FSProto.abort=fileSaverAbort;FSProto.INIT=0;FSProto.WRITING=1;FSProto.DONE=2;FSProto.readyState=FSProto.INIT;FSProto.error=null;FSProto.onwritestart=null;FSProto.onprogress=null;FSProto.onwrite=null;FSProto.onabort=null;FSProto.onerror=null;FSProto.onwriteend=null;function FileSaver(blob,name){this.blob=blob=autoBom(blob);this.saveUsingObjectURLs=saveUsingObjectURLs;this.execSave=execSave;var filesaver=this;var type=blob.type;var blobChanged=false;var objectUrl;var targetView;filesaver.readyState=filesaver.INIT;name=name||'download';if(canUseSaveLink){return saveUsingLinkElement()}fixChromeSaveableType();fixWebKitDownload();if(!reqFs){return saveUsingObjectURLs()}return saveUsingFyleSystem(filesaver);function saveUsingLinkElement(){objectUrl=getURL().createObjectURL(blob);saveLinkElement.href=objectUrl;saveLinkElement.download=name;setImmediate(function(){triggerClickOnSaveLink();dispatchAll(filesaver);revoke(objectUrl);filesaver.readyState=filesaver.DONE},0)}function fixChromeSaveableType(){if(view.chrome&&type&&type!==forceSaveableType){var slice=blob.slice||blob.webkitSlice;blob=slice.call(blob,0,blob.size,forceSaveableType);blobChanged=true}}function fixWebKitDownload(){if(webkitReqFs&&name!=='download'){name+='.download'}if(type===forceSaveableType||webkitReqFs){targetView=view}}function saveUsingObjectURLs(){if(blobChanged||!objectUrl){objectUrl=getURL().createObjectURL(blob)}execSave(objectUrl)}function execSave(objectUrl,file,event){if(targetView){targetView.location.href=objectUrl}else{var newTab=view.open(objectUrl,'_blank');if(newTab===undefined){view.location.href=objectUrl}}filesaver.readyState=filesaver.DONE;if(!event){dispatchAll(filesaver)}else{dispatch(filesaver,'writeend',event)}revoke(file||objectUrl)}}function fileSaverAbort(){var filesaver=this;filesaver.readyState=filesaver.DONE;dispatch(filesaver,'abort')}function dispatchAll(filesaver){dispatch(filesaver,'writestart progress write writeend'.split(' '))}function dispatch(filesaver,eventTypes,event){eventTypes=[].concat(eventTypes);var i=eventTypes.length;while(i--){var listener=filesaver['on'+eventTypes[i]];if(typeof listener==='function'){try{listener.call(filesaver,event||filesaver)}catch(ex){throwOutside(ex)}}}}function saveUsingFyleSystem(filesaver){fsMinSize+=filesaver.blob.size;var createIfNotFound={create:true,exclusive:false};reqFs(view.TEMPORARY,fsMinSize,abortable(getFyleSystem),filesaver.saveUsingObjectURLs);function getFyleSystem(fs){fs.root.getDirectory('temp',createIfNotFound,abortable(getTempDirectory),filesaver.saveUsingObjectURLs)}function getTempDirectory(dir){dir.getFile(name,{create:false},abortable(getExistentFileForRemove),abortable(existentFileNotFound));function getExistentFileForRemove(file){file.remove(function(){save()})}function existentFileNotFound(ex){if(ex.name==='NotFoundError'){save()}else{filesaver.saveUsingObjectURLs()}}function save(){dir.getFile(name,createIfNotFound,abortable(getFileForWrite),filesaver.saveUsingObjectURLs)}function getFileForWrite(file){file.createWriter(abortable(createWriter),filesaver.saveUsingObjectURLs);function createWriter(writer){writer.onwriteend=onWriterEnd;writer.onerror=onError;bindEventsToWriter();writer.write(blob);filesaver.abort=onAbort;filesaver.readyState=filesaver.WRITING;function onWriterEnd(event){filesaver.execSave(file.toURL(),file,event)}function onError(){var error=writer.error;if(error.code!==error.ABORT_ERR){filesaver.saveUsingObjectURLs()}}function bindEventsToWriter(){'writestart progress write abort'.split(' ').forEach(function(event){writer['on'+event]=filesaver['on'+event]})}function onAbort(){writer.abort();filesaver.readyState=filesaver.DONE}}}}function abortable(func){return function(){if(filesaver.readyState!==filesaver.DONE){return func.apply(this,arguments)}}}}function autoBom(blob){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)){return new Blob(['\ufeff',blob],{type:blob.type})}return blob}function getURL(){return view.URL||view.webkitURL||view}function revoke(file){setTimeout(revoker,arbitraryRevokeTimeout);function revoker(){if(typeof file==='string'){getURL().revokeObjectURL(file)}else{file.remove(function(){})}}}function throwOutside(ex){setImmediate(function(){throw ex},0)}function triggerClickOnSaveLink(){var event=new MouseEvent('click');saveLinkElement.dispatchEvent(event)}return saveAs}); |
@@ -1,2 +0,2 @@ | ||
Copyright © 2015 [Eli Grey][1]. | ||
Copyright © 2015 [Carlos A. Gomes][1]. | ||
@@ -9,2 +9,2 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
[1]: http://eligrey.com | ||
[1]: http://carlos-algms.github.io |
{ | ||
"name": "html5-filesaver.js", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "An HTML5 saveAs() FileSaver implementation", | ||
@@ -10,3 +10,3 @@ "main": "FileSaver.js", | ||
}, | ||
"author": "Carlos Gomes", | ||
"author": "Carlos A. Gomes", | ||
"license": "MIT", | ||
@@ -16,3 +16,13 @@ "bugs": { | ||
}, | ||
"homepage": "https://github.com/carlos-algms/FileSaver.js" | ||
"homepage": "https://github.com/carlos-algms/FileSaver.js", | ||
"devDependencies": { | ||
"grunt": "^0.4.5", | ||
"grunt-contrib-concat": "^0.5.1", | ||
"grunt-contrib-jshint": "^0.11.2", | ||
"grunt-contrib-uglify": "^0.9.1", | ||
"grunt-contrib-watch": "^0.6.1", | ||
"jshint-stylish": "^2.0.1", | ||
"load-grunt-tasks": "^3.2.0", | ||
"time-grunt": "^1.2.1" | ||
} | ||
} |
@@ -12,2 +12,9 @@ FileSaver.js | ||
Bower Installation | ||
------------------ | ||
```bash | ||
bower install FileSaver.js --save-dev | ||
``` | ||
Looking for `canvas.toBlob()` for saving canvases? Check out | ||
@@ -22,3 +29,3 @@ [canvas-toBlob.js][2] for a cross-browser implementation. | ||
| Firefox 20+ | Blob | Yes | 800 MiB | None | | ||
| Firefox < 20 | data: URI | No | n/a | [Blob.js](https://github.com/eligrey/Blob.js) | | ||
| Firefox < 20 | data: URI | No | n/a | [Blob.js][5] | | ||
| Chrome | Blob | Yes | [500 MiB][3] | None | | ||
@@ -28,5 +35,5 @@ | Chrome for Android | Blob | Yes | [500 MiB][3] | None | | ||
| Opera 15+ | Blob | Yes | 500 MiB | None | | ||
| Opera < 15 | data: URI | No | n/a | [Blob.js](https://github.com/eligrey/Blob.js) | | ||
| Opera < 15 | data: URI | No | n/a | [Blob.js][5] | | ||
| Safari 6.1+* | Blob | No | ? | None | | ||
| Safari < 6 | data: URI | No | n/a | [Blob.js](https://github.com/eligrey/Blob.js) | | ||
| Safari < 6 | data: URI | No | n/a | [Blob.js][5] | | ||
@@ -49,7 +56,10 @@ Feature detection is possible: | ||
Blobs may be opened instead of saved sometimes—you may have to direct your Safari users to manually | ||
press <kbd>⌘</kbd>+<kbd>S</kbd> to save the file after it is opened. Using the `application/octet-stream` MIME type to force downloads [can cause issues in Safari](https://github.com/eligrey/FileSaver.js/issues/12#issuecomment-47247096). | ||
press <kbd>⌘</kbd>+<kbd>S</kbd> to save the file after it is opened. Using the `application/octet-stream` MIME type | ||
to force downloads [can cause issues in Safari](https://github.com/eligrey/FileSaver.js/issues/12#issuecomment-47247096). | ||
### iOS | ||
saveAs must be run within a user interaction event such as onTouchDown or onClick; setTimeout will prevent saveAs from triggering. Due to restrictions in iOS saveAs opens in a new window instead of downloading, if you want this fixed please [tell Apple](https://bugs.webkit.org/show_bug.cgi?id=102914) how this bug is affecting you. | ||
saveAs must be run within a user interaction event such as onTouchDown or onClick; setTimeout will prevent saveAs from triggering. | ||
Due to restrictions in iOS saveAs opens in a new window instead of downloading, if you want this fixed please | ||
[tell Apple](https://bugs.webkit.org/show_bug.cgi?id=102914) how this bug is affecting you. | ||
@@ -90,10 +100,4 @@ Syntax | ||
![Tracking image](https://in.getclicky.com/212712ns.gif) | ||
![Tracking image](https://in.getclicky.com/100863755ns.gif) | ||
[1]: http://eligrey.com/demos/FileSaver.js/ | ||
[2]: https://github.com/eligrey/canvas-toBlob.js | ||
[3]: https://code.google.com/p/chromium/issues/detail?id=375297 | ||
[4]: https://developer.mozilla.org/en-US/docs/DOM/Blob | ||
[5]: https://github.com/eligrey/Blob.js | ||
[6]: https://github.com/eligrey/canvas-toBlob.js | ||
@@ -103,13 +107,22 @@ Contributing | ||
The `FileSaver.js` distribution file is compiled with Uglify.js like so: | ||
The `FileSaver.js` is the development code, and are not minified. | ||
The `FileSaver.min.js` is the production code, and are minified using uglifyjs. | ||
You need to install [NodeJs][7] and [Grunt][8]. | ||
Installing Dependencies: | ||
```bash | ||
uglifyjs FileSaver.js --comments /@source/ > FileSaver.min.js | ||
npm install | ||
``` | ||
Please make sure you build a production version before submitting a pull request. | ||
Please make sure you run `grunt build` before submitting a pull request. | ||
Bower Installation | ||
------------------ | ||
Please see the [this repo](http://github.com/Teleborder/FileSaver.js) for a bower-compatible fork of FileSaver.js, available under the package name `file-saver.js`. | ||
[1]: http://eligrey.com/demos/FileSaver.js/ | ||
[2]: https://github.com/eligrey/canvas-toBlob.js | ||
[3]: https://code.google.com/p/chromium/issues/detail?id=375297 | ||
[4]: https://developer.mozilla.org/en-US/docs/DOM/Blob | ||
[5]: https://github.com/eligrey/Blob.js | ||
[6]: https://github.com/eligrey/canvas-toBlob.js | ||
[7]: https://nodejs.org/download/ | ||
[8]: http://gruntjs.com/getting-started |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40692
21
865
123
8
1