10 Commits
Author SHA1 Message Date
Jimmy Wärting 0b9d514107 docs for using url 2018-09-21 16:26:24 +02:00
Jimmy Wärting 17403f0731 don’t crash in worker 2018-09-21 16:16:50 +02:00
Jimmy Wärting 0718d9f852 new version 2018-09-21 16:10:37 +02:00
Jimmy Wärting ae32ccca4d include the list folder 2018-09-21 14:56:39 +02:00
Jimmy Wärting dcdc67deec update dev rep 2018-09-21 14:56:20 +02:00
Jimmy Wärting 465b00f11b remove old demos 2018-09-21 14:54:47 +02:00
Owen BlackerandJimmy Wärting 5db588a568 Amended link to Apple's WebKit bug (#454)
WebKit bug №102914 is no longer the ticket referencing the "iOS can't do this" problem — that ticket has been closed since it was resolved on MacOS.

The appropriate WebKit bug ticket is №167341: [iOS] Add support for the download attribute, so I have updated the link appropriately.
2018-09-20 23:18:25 +02:00
Jimmy WärtingandGitHub 1144ac42bb Add precaution note about file constructor
closes #455
2018-08-07 19:44:51 +02:00
Eli GreyandGitHub 00e540fda5 Merge pull request #450 from ps011/master
Added import statement in syntax section for ease of use
2018-07-17 10:50:43 -07:00
Soni 23d400231f Added import statement in syntax section for ease of use 2018-07-03 14:31:01 +05:30
14 changed files with 348 additions and 3317 deletions
-19
View File
@@ -1,19 +0,0 @@
{
"presets": [
["env", {
"targets": {
"browsers": [
"ie > 9"
]
}
}]
],
"plugins": [
"transform-es2015-modules-umd"
],
"env": {
"production": {
"presets": ["minify"]
}
}
}
-3
View File
@@ -1,6 +1,3 @@
node_modules/ node_modules/
.DS_Store .DS_Store
.idea/ .idea/
# Generated files
/dist/
+22 -6
View File
@@ -1,4 +1,4 @@
If you need to save really large files bigger then the blob's size limitation or don't have If you need to save really large files bigger then the blob's size limitation or don't have
enough RAM, then have a look at the more advanced [StreamSaver.js](https://github.com/jimmywarting/StreamSaver.js) enough RAM, then have a look at the more advanced [StreamSaver.js](https://github.com/jimmywarting/StreamSaver.js)
that can save data directly to the hard drive asynchronously with the power of the new streams API. That will have that can save data directly to the hard drive asynchronously with the power of the new streams API. That will have
support for progress, cancelation and knowing when it's done writing support for progress, cancelation and knowing when it's done writing
@@ -54,16 +54,20 @@ press <kbd>⌘</kbd>+<kbd>S</kbd> to save the file after it is opened. Using the
### iOS ### 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 how this WebKit bug is affecting you](https://bugs.webkit.org/show_bug.cgi?id=167341).
Syntax Syntax
------ ------
### Import saveAs() from file-saver
```js ```js
FileSaver saveAs(Blob/File data, optional DOMString filename, optional Boolean disableAutoBOM) import { saveAs } from 'file-saver/FileSaver';
``` ```
Pass `true` for `disableAutoBOM` if you don't want FileSaver.js to automatically provide Unicode text encoding hints (see: [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark)). ```js
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Boolean autoBOM)
```
Pass `true` for `autoBOM` if you don't want FileSaver.js to automatically provide Unicode text encoding hints (see: [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark)).
Examples Examples
-------- --------
@@ -82,6 +86,16 @@ var blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(blob, "hello world.txt"); FileSaver.saveAs(blob, "hello world.txt");
``` ```
### Saving urls
```js
FileSaver.saveAs("https://httpbin.org/image", "image.jpg");
```
Using urls within the same origin will just use `a[download]`
Otherwise it will first check if it supports cors header with a synchronously head request
if it dose it will download the data and save it using blob urls
if not it will try to download it using `a[download]`
The standard W3C File API [`Blob`][4] interface is not available in all browsers. The standard W3C File API [`Blob`][4] interface is not available in all browsers.
[Blob.js][5] is a cross-browser `Blob` implementation that solves this. [Blob.js][5] is a cross-browser `Blob` implementation that solves this.
@@ -102,10 +116,12 @@ Note: The standard HTML5 `canvas.toBlob()` method is not available in all browse
You can save a File constructor without specifying a filename. The You can save a File constructor without specifying a filename. The
File itself already contains a name, There is a hand full of ways to get a file File itself already contains a name, There is a hand full of ways to get a file
instance (from storage, file input, new constructor) instance (from storage, file input, new constructor, clipboard event)
But if you still want to change the name, then you can change it in the 2nd argument But if you still want to change the name, then you can change it in the 2nd argument
```js ```js
// Note: Ie and Edge don't support the new File constructor,
// so it's better to construct blobs and use saveAs(blob, filename)
var file = new File(["Hello, world!"], "hello world.txt", {type: "text/plain;charset=utf-8"}); var file = new File(["Hello, world!"], "hello world.txt", {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(file); FileSaver.saveAs(file);
``` ```
+3 -2
View File
@@ -1,7 +1,7 @@
{ {
"name": "file-saver", "name": "file-saver",
"main": "dist/FileSaver.js", "main": "dist/FileSaver.min.js",
"version": "1.3.8", "version": "2.0.0-rc.1",
"homepage": "https://github.com/eligrey/FileSaver.js", "homepage": "https://github.com/eligrey/FileSaver.js",
"authors": [ "authors": [
"Eli Grey <[email protected]>" "Eli Grey <[email protected]>"
@@ -16,6 +16,7 @@
"ignore": [ "ignore": [
"*", "*",
"!FileSaver.*js", "!FileSaver.*js",
"!FileSaver.*map",
"!LICENSE.md" "!LICENSE.md"
] ]
} }
-50
View File
@@ -1,50 +0,0 @@
html {
background-color: #DDD;
}
body {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
width: 900px;
margin: 0 auto;
font-family: Verdana, Helvetica, Arial, sans-serif;
-webkit-box-shadow: 0 0 10px 2px rgba(0, 0, 0, .5);
-moz-box-shadow: 0 0 10px 2px rgba(0, 0, 0, .5);
box-shadow: 0 0 10px 2px rgba(0, 0, 0, .5);
padding: 7px 25px 70px;
background-color: #FFF;
}
h1, h2, h3, h4, h5, h6 {
font-family: Georgia, "Times New Roman", serif;
}
h2, form {
text-align: center;
}
form {
margin-top: 5px;
}
.input {
width: 500px;
height: 300px;
margin: 0 auto;
display: block;
}
section {
margin-top: 40px;
}
#canvas {
cursor: crosshair;
}
#canvas, #html {
border: 1px solid #000;
}
.filename {
text-align: right;
}
#html {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: auto;
padding: 1em;
}
-216
View File
@@ -1,216 +0,0 @@
/*! FileSaver.js demo script
* 2016-05-26
*
* By Eli Grey, http://eligrey.com
* License: 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) {
"use strict";
// The canvas drawing portion of the demo is based off the demo at
// http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/
var
document = view.document
, $ = function(id) {
return document.getElementById(id);
}
, session = view.sessionStorage
// only get URL when necessary in case Blob.js hasn't defined it yet
, get_blob = function() {
return view.Blob;
}
, canvas = $("canvas")
, canvas_options_form = $("canvas-options")
, canvas_filename = $("canvas-filename")
, canvas_clear_button = $("canvas-clear")
, text = $("text")
, text_options_form = $("text-options")
, text_filename = $("text-filename")
, html = $("html")
, html_options_form = $("html-options")
, html_filename = $("html-filename")
, ctx = canvas.getContext("2d")
, drawing = false
, x_points = session.x_points || []
, y_points = session.y_points || []
, drag_points = session.drag_points || []
, add_point = function(x, y, dragging) {
x_points.push(x);
y_points.push(y);
drag_points.push(dragging);
}
, draw = function(){
canvas.width = canvas.width;
ctx.lineWidth = 6;
ctx.lineJoin = "round";
ctx.strokeStyle = "#000000";
var
i = 0
, len = x_points.length
;
for(; i < len; i++) {
ctx.beginPath();
if (i && drag_points[i]) {
ctx.moveTo(x_points[i-1], y_points[i-1]);
} else {
ctx.moveTo(x_points[i]-1, y_points[i]);
}
ctx.lineTo(x_points[i], y_points[i]);
ctx.closePath();
ctx.stroke();
}
}
, stop_drawing = function() {
drawing = false;
}
// Title guesser and document creator available at https://gist.github.com/1059648
, guess_title = function(doc) {
var
h = "h6 h5 h4 h3 h2 h1".split(" ")
, i = h.length
, headers
, header_text
;
while (i--) {
headers = doc.getElementsByTagName(h[i]);
for (var j = 0, len = headers.length; j < len; j++) {
header_text = headers[j].textContent.trim();
if (header_text) {
return header_text;
}
}
}
}
, doc_impl = document.implementation
, create_html_doc = function(html) {
var
dt = doc_impl.createDocumentType('html', null, null)
, doc = doc_impl.createDocument("http://www.w3.org/1999/xhtml", "html", dt)
, doc_el = doc.documentElement
, head = doc_el.appendChild(doc.createElement("head"))
, charset_meta = head.appendChild(doc.createElement("meta"))
, title = head.appendChild(doc.createElement("title"))
, body = doc_el.appendChild(doc.createElement("body"))
, i = 0
, len = html.childNodes.length
;
charset_meta.setAttribute("charset", html.ownerDocument.characterSet);
for (; i < len; i++) {
body.appendChild(doc.importNode(html.childNodes.item(i), true));
}
var title_text = guess_title(doc);
if (title_text) {
title.appendChild(doc.createTextNode(title_text));
}
return doc;
}
;
canvas.width = 500;
canvas.height = 300;
if (typeof x_points === "string") {
x_points = JSON.parse(x_points);
} if (typeof y_points === "string") {
y_points = JSON.parse(y_points);
} if (typeof drag_points === "string") {
drag_points = JSON.parse(drag_points);
} if (session.canvas_filename) {
canvas_filename.value = session.canvas_filename;
} if (session.text) {
text.value = session.text;
} if (session.text_filename) {
text_filename.value = session.text_filename;
} if (session.html) {
html.innerHTML = session.html;
} if (session.html_filename) {
html_filename.value = session.html_filename;
}
drawing = true;
draw();
drawing = false;
canvas_clear_button.addEventListener("click", function() {
canvas.width = canvas.width;
x_points.length =
y_points.length =
drag_points.length =
0;
}, false);
canvas.addEventListener("mousedown", function(event) {
event.preventDefault();
drawing = true;
add_point(event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop, false);
draw();
}, false);
canvas.addEventListener("mousemove", function(event) {
if (drawing) {
add_point(event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop, true);
draw();
}
}, false);
canvas.addEventListener("mouseup", stop_drawing, false);
canvas.addEventListener("mouseout", stop_drawing, false);
canvas_options_form.addEventListener("submit", function(event) {
event.preventDefault();
canvas.toBlobHD(function(blob) {
saveAs(
blob
, (canvas_filename.value || canvas_filename.placeholder) + ".png"
);
}, "image/png");
}, false);
text_options_form.addEventListener("submit", function(event) {
event.preventDefault();
var BB = get_blob();
saveAs(
new BB(
[text.value || text.placeholder]
, {type: "text/plain;charset=" + document.characterSet}
)
, (text_filename.value || text_filename.placeholder) + ".txt"
);
}, false);
html_options_form.addEventListener("submit", function(event) {
event.preventDefault();
var
BB = get_blob()
, xml_serializer = new XMLSerializer()
, doc = create_html_doc(html)
;
saveAs(
new BB(
[xml_serializer.serializeToString(doc)]
, {type: "text/plain;charset=" + document.characterSet}
)
, (html_filename.value || html_filename.placeholder) + ".xhtml"
);
}, false);
view.addEventListener("unload", function() {
session.x_points = JSON.stringify(x_points);
session.y_points = JSON.stringify(y_points);
session.drag_points = JSON.stringify(drag_points);
session.canvas_filename = canvas_filename.value;
session.text = text.value;
session.text_filename = text_filename.value;
session.html = html.innerHTML;
session.html_filename = html_filename.value;
}, false);
}(self));
-2
View File
@@ -1,2 +0,0 @@
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/demo/demo.js */
(function(n){"use strict";var s=n.document,g=function(A){return s.getElementById(A)},b=n.sessionStorage,x=function(){return n.Blob},f=g("canvas"),r=g("canvas-options"),y=g("canvas-filename"),p=g("canvas-clear"),q=g("text"),t=g("text-options"),h=g("text-filename"),m=g("html"),e=g("html-options"),i=g("html-filename"),u=f.getContext("2d"),z=false,a=b.x_points||[],o=b.y_points||[],d=b.drag_points||[],j=function(A,C,B){a.push(A);o.push(C);d.push(B)},l=function(){f.width=f.width;u.lineWidth=6;u.lineJoin="round";u.strokeStyle="#000000";var B=0,A=a.length;for(;B<A;B++){u.beginPath();if(B&&d[B]){u.moveTo(a[B-1],o[B-1])}else{u.moveTo(a[B]-1,o[B])}u.lineTo(a[B],o[B]);u.closePath();u.stroke()}},c=function(){z=false},w=function(E){var D="h6 h5 h4 h3 h2 h1".split(" "),C=D.length,F,G;while(C--){F=E.getElementsByTagName(D[C]);for(var B=0,A=F.length;B<A;B++){G=F[B].textContent.trim();if(G){return G}}}},v=s.implementation,k=function(D){var B=v.createDocumentType("html",null,null),J=v.createDocument("http://www.w3.org/1999/xhtml","html",B),A=J.documentElement,H=A.appendChild(J.createElement("head")),K=H.appendChild(J.createElement("meta")),I=H.appendChild(J.createElement("title")),E=A.appendChild(J.createElement("body")),C=0,G=D.childNodes.length;K.setAttribute("charset",D.ownerDocument.characterSet);for(;C<G;C++){E.appendChild(J.importNode(D.childNodes.item(C),true))}var F=w(J);if(F){I.appendChild(J.createTextNode(F))}return J};f.width=500;f.height=300;if(typeof a==="string"){a=JSON.parse(a)}if(typeof o==="string"){o=JSON.parse(o)}if(typeof d==="string"){d=JSON.parse(d)}if(b.canvas_filename){y.value=b.canvas_filename}if(b.text){q.value=b.text}if(b.text_filename){h.value=b.text_filename}if(b.html){m.innerHTML=b.html}if(b.html_filename){i.value=b.html_filename}z=true;l();z=false;p.addEventListener("click",function(){f.width=f.width;a.length=o.length=d.length=0},false);f.addEventListener("mousedown",function(A){A.preventDefault();z=true;j(A.pageX-f.offsetLeft,A.pageY-f.offsetTop,false);l()},false);f.addEventListener("mousemove",function(A){if(z){j(A.pageX-f.offsetLeft,A.pageY-f.offsetTop,true);l()}},false);f.addEventListener("mouseup",c,false);f.addEventListener("mouseout",c,false);r.addEventListener("submit",function(A){A.preventDefault();f.toBlobHD(function(B){saveAs(B,(y.value||y.placeholder)+".png")},"image/png")},false);t.addEventListener("submit",function(A){A.preventDefault();var B=x();saveAs(new B([q.value||q.placeholder],{type:"text/plain;charset="+s.characterSet}),(h.value||h.placeholder)+".txt")},false);e.addEventListener("submit",function(B){B.preventDefault();var D=x(),A=new XMLSerializer,C=k(m);saveAs(new D([A.serializeToString(C)],{type:"text/plain;charset="+s.characterSet}),(i.value||i.placeholder)+".xhtml")},false);n.addEventListener("unload",function(){b.x_points=JSON.stringify(a);b.y_points=JSON.stringify(o);b.drag_points=JSON.stringify(d);b.canvas_filename=y.value;b.text=q.value;b.text_filename=h.value;b.html=m.innerHTML;b.html_filename=i.value},false)}(self));
-57
View File
@@ -1,57 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US-x-Hixie">
<head>
<meta charset="utf-8"/>
<title>FileSaver.js demo</title>
<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/eligrey/FileSaver.js/702cd2e820b680f88a0f299e33085c196806fc52/demo/demo.css"/>
</head>
<body>
<h1><a href="https://github.com/eligrey/FileSaver.js">FileSaver.js</a> demo</h1>
<p>
The following examples demonstrate how it is possible to generate and save any type of data right in the browser using the <code>saveAs()</code> FileSaver interface, without contacting any servers.
</p>
<section id="image-demo">
<h2>Saving an image</h2>
<canvas class="input" id="canvas" width="500" height="300"/>
<form id="canvas-options">
<label>Filename: <input type="text" class="filename" id="canvas-filename" placeholder="doodle"/>.png</label>
<input type="submit" value="Save"/>
<input type="button" id="canvas-clear" value="Clear"/>
</form>
</section>
<section id="text-demo">
<h2>Saving text</h2>
<textarea class="input" id="text" placeholder="Once upon a time..."/>
<form id="text-options">
<label>Filename: <input type="text" class="filename" id="text-filename" placeholder="a plain document"/>.txt</label>
<input type="submit" value="Save"/>
</form>
</section>
<section id="html-demo">
<h2>Saving rich text</h2>
<div class="input" id="html" contenteditable="">
<h3>Some example rich text</h3>
<ul>
<li><del>Plain</del> <ins>Boring</ins> text.</li>
<li><em>Emphasized text!</em></li>
<li><strong>Strong text!</strong></li>
<li>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="70" height="70">
<circle cx="35" cy="35" r="35" fill="red"/>
<text x="10" y="40">image</text>
</svg>
</li>
<li><a href="https://github.com/eligrey/FileSaver.js">A link.</a></li>
</ul>
</div>
<form id="html-options">
<label>Filename: <input type="text" class="filename" id="html-filename" placeholder="a rich document"/>.xhtml</label>
<input type="submit" value="Save"/>
</form>
</section>
<script async="" src="https://cdn.rawgit.com/eligrey/Blob.js/0cef2746414269b16834878a8abc52eb9d53e6bd/Blob.js"/>
<script async="" src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"/>
<script async="" src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"/>
<script async="" src="https://cdn.rawgit.com/eligrey/FileSaver.js/597b6cd0207ce408a6d34890b5b2826b13450714/demo/demo.js"/>
</body>
</html>
+170
View File
@@ -0,0 +1,170 @@
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(["exports"], factory);
} else if (typeof exports !== "undefined") {
factory(exports);
} else {
var mod = {
exports: {}
};
factory(mod.exports);
global.FileSaver = mod.exports;
}
})(this, function (_exports) {
"use strict";
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.default = void 0;
/*
* FileSaver.js
* A saveAs() FileSaver implementation.
*
* By Eli Grey, http://eligrey.com
*
* License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
* source : http://purl.eligrey.com/github/FileSaver.js
*/
// The one and only way of getting global scope in all enviorment
// https://stackoverflow.com/q/3277182/1008999
var _global = function () {
// some use content security policy to disable eval
try {
return Function('return this')() || (42, eval)('this');
} catch (e) {
// every global should have circular reference
// used for checking if someone writes var window = {}; var self = {}
return typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : this;
}
}();
function bom(blob, autoBom) {
if (!autoBom) return 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;
}
function download(url, name, autoBom) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = function () {
saveAs(xhr.response, name, autoBom);
};
xhr.onerror = function () {
console.error('could not download file');
};
xhr.send();
}
function corsEnabled(url) {
var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker
xhr.open('HEAD', url, false);
xhr.send();
return xhr.status >= 200 && xhr.status <= 299;
}
var saveAs = _global.saveAs || // probably in some web worker
typeof window !== 'object' || window !== _global ? function saveAs() {}
/* noop */
// Use download attribute first if possible (#193 Lumia mobile)
: 'download' in HTMLAnchorElement.prototype ? function saveAs(blob, name, autoBom) {
var URL = _global.URL || _global.webkitURL;
var a = document.createElement('a');
name = name || blob.name || 'download';
a.download = name;
a.rel = 'noopener'; // tabnabbing
// TODO: detect chrome extensions & packaged apps
// a.target = '_blank'
if (typeof blob === 'string') {
// Support regular links
a.href = blob;
if (a.origin !== location.origin) {
corsEnabled(a.href) ? download(blob, name, autoBom) : a.click(a.target = '_blank');
} else {
a.click();
}
} else {
// Support blobs
a.href = URL.createObjectURL(blob);
setTimeout(function () {
URL.revokeObjectURL(a.href);
}, 4E4); // 40s
setTimeout(a.click.bind(a), 0);
}
} // Use msSaveOrOpenBlob as a second approch
: 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, autoBom) {
name = name || blob.name || 'download';
if (typeof blob === 'string') {
if (corsEnabled(blob)) {
download(blob, name, autoBom);
} else {
var a = document.createElement('a');
a.href = blob;
a.target = '_blank';
setTimeout(a.click.bind(a));
}
} else {
navigator.msSaveOrOpenBlob(bom(blob, autoBom), name);
}
} // Fallback to using FileReader and a popup
: function saveAs(blob, name, autoBom, popup) {
// Open a popup immediately do go around popup blocker
// Mostly only avalible on user interaction and the fileReader is async so...
popup = popup || open('', '_blank');
if (popup) {
popup.document.title = popup.document.body.innerText = 'downloading...';
}
if (typeof blob === 'string') return download(blob, name, autoBom);
var force = blob.type === 'application/octet-stream';
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
if ((isChromeIOS || force && isSafari) && typeof FileReader === 'object') {
// Safari doesn't allow downloading of blob urls
var reader = new FileReader();
reader.onloadend = function () {
var url = reader.result;
url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
if (popup) popup.location.href = url;else location = url;
popup = null; // reverse-tabnabbing #460
};
reader.readAsDataURL(blob);
} else {
var URL = _global.URL || _global.webkitURL;
var url = URL.createObjectURL(blob);
if (popup) popup.location = url;else location.href = url;
popup = null; // reverse-tabnabbing #460
setTimeout(function () {
URL.revokeObjectURL(url);
}, 4E4); // 40s
}
};
_global.saveAs = saveAs;
var _default = saveAs;
_exports.default = _default;
});
+3
View File
@@ -0,0 +1,3 @@
(function(a,b){if("function"==typeof define&&define.amd)define(["exports"],b);else if("undefined"!=typeof exports)b(exports);else{var c={exports:{}};b(c.exports),a.FileSaver=c.exports}})(this,function(a){"use strict";function b(a,b){return b?/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a:a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){f(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;return b.open("HEAD",a,!1),b.send(),200<=b.status&&299>=b.status}Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var e=function(){try{return Function("return this")()||(42,eval)("this")}catch(a){return"object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:this}}(),f=e.saveAs||"object"!=typeof window||window!==e?function(){}:"download"in HTMLAnchorElement.prototype?function(b,f,g){var h=e.URL||e.webkitURL,i=document.createElement("a");f=f||b.name||"download",i.download=f,i.rel="noopener","string"==typeof b?(i.href=b,i.origin===location.origin?i.click():d(i.href)?c(b,f,g):i.click(i.target="_blank")):(i.href=h.createObjectURL(b),setTimeout(function(){h.revokeObjectURL(i.href)},4E4),setTimeout(i.click.bind(i),0))}:"msSaveOrOpenBlob"in navigator?function(e,f,g){if(f=f||e.name||"download","string"!=typeof e)navigator.msSaveOrOpenBlob(b(e,g),f);else if(d(e))c(e,f,g);else{var h=document.createElement("a");h.href=e,h.target="_blank",setTimeout(h.click.bind(h))}}:function(a,b,d,f){if(f=f||open("","_blank"),f&&(f.document.title=f.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(e.HTMLElement)||e.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),f?f.location.href=a:location=a,f=null},j.readAsDataURL(a)}else{var k=e.URL||e.webkitURL,l=k.createObjectURL(a);f?f.location=l:location.href=l,f=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}};e.saveAs=f;a.default=f});
//# sourceMappingURL=FileSaver.min.js.map
+1
View File
File diff suppressed because one or more lines are too long
-2783
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -1,8 +1,8 @@
{ {
"name": "file-saver", "name": "file-saver",
"version": "1.3.8", "version": "2.0.0-rc.1",
"description": "An HTML5 saveAs() FileSaver implementation", "description": "An HTML5 saveAs() FileSaver implementation",
"main": "dist/FileSaver.js", "main": "dist/FileSaver.min.js",
"module": "src/FileSaver.js", "module": "src/FileSaver.js",
"files": [ "files": [
"dist/FileSaver.js", "dist/FileSaver.js",
@@ -11,8 +11,8 @@
], ],
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 0", "test": "echo \"Error: no test specified\" && exit 0",
"build:development": "mkdir -p dist && babel src/FileSaver.js --out-file=dist/FileSaver.js", "build:development": "babel -o dist/FileSaver.js --plugins @babel/plugin-transform-modules-umd src/FileSaver.js",
"build:production": "NODE_ENV=production npm run build:development -- --out-file=dist/FileSaver.min.js", "build:production": "babel -o dist/FileSaver.min.js -s --plugins @babel/plugin-transform-modules-umd --presets minify src/FileSaver.js",
"build": "npm run build:development && npm run build:production", "build": "npm run build:development && npm run build:production",
"prepublishOnly": "npm run build" "prepublishOnly": "npm run build"
}, },
@@ -32,9 +32,9 @@
}, },
"homepage": "https://github.com/eligrey/FileSaver.js#readme", "homepage": "https://github.com/eligrey/FileSaver.js#readme",
"devDependencies": { "devDependencies": {
"babel-cli": "^6.26.0", "@babel/cli": "^7.1.0",
"babel-plugin-transform-es2015-modules-umd": "^6.24.1", "@babel/core": "^7.1.0",
"babel-preset-env": "^1.6.1", "@babel/plugin-transform-modules-umd": "^7.1.0",
"babel-preset-minify": "^0.2.0" "babel-preset-minify": "^0.4.3"
} }
} }
+141 -171
View File
@@ -1,182 +1,152 @@
/* FileSaver.js /*
* A saveAs() FileSaver implementation. * FileSaver.js
* 1.3.8 * A saveAs() FileSaver implementation.
* 2018-03-22 14:03:47 *
* * By Eli Grey, http://eligrey.com
* By Eli Grey, https://eligrey.com *
* License: MIT * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md * source : http://purl.eligrey.com/github/FileSaver.js
*/ */
/*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/src/FileSaver.js */ // The one and only way of getting global scope in all enviorment
// https://stackoverflow.com/q/3277182/1008999
var _global = (function () {
// some use content security policy to disable eval
try {
return Function('return this')() || (42, eval)('this')
} catch (e) {
// every global should have circular reference
// used for checking if someone writes var window = {}; var self = {}
return typeof window === 'object' && window.window === window ? window
: typeof self === 'object' && self.self === self ? self
: typeof global === 'object' && global.global === global ? global : this
}
})()
export var saveAs = saveAs || (function(view) { function bom (blob, autoBom) {
"use strict"; if (!autoBom) return blob
// IE <10 is explicitly unsupported // prepend BOM for UTF-8 XML and text/* types (including HTML)
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
return; 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 })
var }
doc = view.document return blob
// 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)
, setImmediate = view.setImmediate || view.setTimeout
, throw_outside = function(ex) {
setImmediate(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) { function download (url, name, autoBom) {
object_url = get_URL().createObjectURL(blob); var xhr = new XMLHttpRequest()
setImmediate(function() { xhr.open('GET', url)
save_link.href = object_url; xhr.responseType = 'blob'
save_link.download = name; xhr.onload = function () {
click(save_link); saveAs(xhr.response, name, autoBom)
dispatch_all(); }
revoke(object_url); xhr.onerror = function () {
filesaver.readyState = filesaver.DONE; console.error('could not download file')
}, 0); }
return; xhr.send()
} }
fs_error(); function corsEnabled (url) {
} var xhr = new XMLHttpRequest()
, FS_proto = FileSaver.prototype // use sync to avoid popup blocker
, saveAs = function(blob, name, no_auto_bom) { xhr.open('HEAD', url, false)
return new FileSaver(blob, name || blob.name || "download", no_auto_bom); xhr.send()
} return xhr.status >= 200 && xhr.status <= 299
; }
// IE 10+ (native saveAs) var saveAs = _global.saveAs ||
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { // probably in some web worker
return function(blob, name, no_auto_bom) { (typeof window !== 'object' || window !== _global)
name = name || blob.name || "download"; ? function saveAs () { /* noop */ }
if (!no_auto_bom) { // Use download attribute first if possible (#193 Lumia mobile)
blob = auto_bom(blob); : 'download' in HTMLAnchorElement.prototype
} ? function saveAs (blob, name, autoBom) {
return navigator.msSaveOrOpenBlob(blob, name); var URL = _global.URL || _global.webkitURL
}; var a = document.createElement('a')
} name = name || blob.name || 'download'
// todo: detect chrome extensions & packaged apps a.download = name
//save_link.target = "_blank"; a.rel = 'noopener' // tabnabbing
FS_proto.abort = function(){}; // TODO: detect chrome extensions & packaged apps
FS_proto.readyState = FS_proto.INIT = 0; // a.target = '_blank'
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error = if (typeof blob === 'string') {
FS_proto.onwritestart = // Support regular links
FS_proto.onprogress = a.href = blob
FS_proto.onwrite = if (a.origin !== location.origin) {
FS_proto.onabort = corsEnabled(a.href)
FS_proto.onerror = ? download(blob, name, autoBom)
FS_proto.onwriteend = : a.click(a.target = '_blank')
null; } else {
a.click()
}
} else {
// Support blobs
a.href = URL.createObjectURL(blob)
setTimeout(function () { URL.revokeObjectURL(a.href) }, 4E4) // 40s
setTimeout(a.click.bind(a), 0)
}
}
return saveAs; // Use msSaveOrOpenBlob as a second approch
}( : 'msSaveOrOpenBlob' in navigator
typeof self !== "undefined" && self ? function saveAs (blob, name, autoBom) {
|| typeof window !== "undefined" && window name = name || blob.name || 'download'
|| this
)); if (typeof blob === 'string') {
if (corsEnabled(blob)) {
download(blob, name, autoBom)
} else {
var a = document.createElement('a')
a.href = blob
a.target = '_blank'
setTimeout(a.click.bind(a))
}
} else {
navigator.msSaveOrOpenBlob(bom(blob, autoBom), name)
}
}
// Fallback to using FileReader and a popup
: function saveAs (blob, name, autoBom, popup) {
// Open a popup immediately do go around popup blocker
// Mostly only avalible on user interaction and the fileReader is async so...
popup = popup || open('', '_blank')
if (popup) {
popup.document.title =
popup.document.body.innerText = 'downloading...'
}
if (typeof blob === 'string') return download(blob, name, autoBom)
var force = blob.type === 'application/octet-stream'
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari
var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent)
if ((isChromeIOS || (force && isSafari)) && typeof FileReader === 'object') {
// Safari doesn't allow downloading of blob urls
var reader = new FileReader()
reader.onloadend = function () {
var url = reader.result
url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;')
if (popup) popup.location.href = url
else location = url
popup = null // reverse-tabnabbing #460
}
reader.readAsDataURL(blob)
} else {
var URL = _global.URL || _global.webkitURL
var url = URL.createObjectURL(blob)
if (popup) popup.location = url
else location.href = url
popup = null // reverse-tabnabbing #460
setTimeout(function () { URL.revokeObjectURL(url) }, 4E4) // 40s
}
}
_global.saveAs = saveAs
export default saveAs