From af944ad28fc5879bf9e7f38d75dfb84b2dc289b3 Mon Sep 17 00:00:00 2001 From: David Duponchel Date: Thu, 26 May 2016 20:38:20 +0200 Subject: [PATCH] Support Promise[Blob]. The old code didn't accept promises containing blobs which cause issues when working with canvas. There are two ways to get a binary content from a canvas: `canvas.toDataURL()` and `canvas.toBlob()`. Working with the first one involves a substring to remove the data url part and a base64 decode. The other one ends up with a Promise[Blob], fixed by this commit. Now, we can extract the binary content of a canvas like: ```js var p = new JSZip.external.Promise(function (resolve, reject) { canvas.toBlob(function (blob) { resolve(blob); }); }); ``` --- lib/utils.js | 35 ++++++++++++++-------------- test/asserts/file.js | 55 +++++++++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index d79e0110..291c1d4e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -418,23 +418,24 @@ exports.extend = function() { */ exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { - var promise = null; - if (support.blob && inputData instanceof Blob && typeof FileReader !== "undefined") { - promise = new external.Promise(function (resolve, reject) { - var reader = new FileReader(); - - reader.onload = function(e) { - resolve(e.target.result); - }; - reader.onerror = function(e) { - reject(e.target.error); - }; - reader.readAsArrayBuffer(inputData); - }); - } else { - // if data is already a promise, this flatten it. - promise = external.Promise.resolve(inputData); - } + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + if (support.blob && data instanceof Blob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); return promise.then(function(data) { var dataType = exports.getTypeOf(data); diff --git a/test/asserts/file.js b/test/asserts/file.js index 7ea078ce..1353ed30 100644 --- a/test/asserts/file.js +++ b/test/asserts/file.js @@ -4,6 +4,21 @@ QUnit.module("file", function () { + function str2blob (str) { + var u8 = new Uint8Array(str.length); + for(var i = 0; i < str.length; i++) { + u8[i] = str.charCodeAt(i); + } + try { + // don't use an Uint8Array, see the comment on utils.newBlob + return new Blob([u8.buffer], {type:"text/plain"}); + } catch (e) { + var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; + var builder = new Builder(); + builder.append(u8.buffer); + return builder.getBlob("text/plain"); + } + } QUnit.module("add"); @@ -356,21 +371,6 @@ QUnit.module("file", function () { if (JSZip.support.blob) { test("add file: file(name, Blob)", function() { - var str2blob = function (str) { - var array = new Uint8Array(str.length); - for(var i = 0; i < str.length; i++) { - array[i] = str.charCodeAt(i); - } - try { - // don't use an Uint8Array, see the comment on utils.newBlob - return new Blob([array.buffer], {type:"text/plain"}); - } catch (e) { - var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; - var builder = new Builder(); - builder.append(array.buffer); - return builder.getBlob("text/plain"); - } - }; var zip = new JSZip(); zip.file("file.txt", str2blob("\xE2\x82\xAC15\n")); testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"}); @@ -408,7 +408,7 @@ QUnit.module("file", function () { }); } - test("add file: file(name, polyfill Promise)", function() { + test("add file: file(name, polyfill Promise[string])", function() { var str2promise = function (str) { return new JSZip.external.Promise(function(resolve, reject) { setTimeout(function () { @@ -429,6 +429,29 @@ QUnit.module("file", function () { testFileDataGetters({name : "empty content", zip : zip, textData : ""}); }); + if (JSZip.support.blob) { + test("add file: file(name, polyfill Promise[Blob])", function() { + var str2promiseOfBlob = function (str) { + return new JSZip.external.Promise(function(resolve, reject) { + setTimeout(function () { + resolve(str2blob(str)); + }, 10); + }); + }; + var zip = new JSZip(); + zip.file("file.txt", str2promiseOfBlob("\xE2\x82\xAC15\n")); + testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"}); + + zip = new JSZip(); + zip.file("file.txt", str2promiseOfBlob("test\r\ntest\r\n")); + testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"}); + + zip = new JSZip(); + zip.file("file.txt", str2promiseOfBlob("")); + testFileDataGetters({name : "empty content", zip : zip, textData : ""}); + }); + } + if (JSZip.support.nodebuffer) { test("add file: file(name, Buffer)", function() { var str2buffer = function (str) {