Accept a Blob as input in Zotero.File.putContentsAsync()

This commit is contained in:
Dan Stillman 2018-09-06 13:44:09 -04:00
parent 36afb34cf6
commit 18821984e0
3 changed files with 55 additions and 13 deletions

View file

@ -398,11 +398,11 @@ Zotero.File = new function(){
* Write data to a file asynchronously
*
* @param {String|nsIFile} - String path or nsIFile to write to
* @param {String|nsIInputStream} data - The string or nsIInputStream to write to the file
* @param {String|nsIInputStream|ArrayBuffer} data - The data to write to the file
* @param {String} [charset] - The character set; defaults to UTF-8
* @return {Promise} - A promise that is resolved when the file has been written
*/
this.putContentsAsync = function (path, data, charset) {
this.putContentsAsync = async function (path, data, charset) {
if (path instanceof Ci.nsIFile) {
path = path.path;
}
@ -418,16 +418,33 @@ Zotero.File = new function(){
));
}
var deferred = Zotero.Promise.defer();
var os = FileUtils.openSafeFileOutputStream(new FileUtils.File(path));
NetUtil.asyncCopy(data, os, function(inputStream, status) {
if (!Components.isSuccessCode(status)) {
deferred.reject(new Components.Exception("File write operation failed", status));
return;
}
deferred.resolve();
// If Blob, feed that to an input stream
//
// data instanceof Blob doesn't work in XPCOM
if (typeof data.size != 'undefined' && typeof data.slice == 'function') {
let arrayBuffer = await new Zotero.Promise(function (resolve) {
let fr = new FileReader();
fr.addEventListener("loadend", function() {
resolve(fr.result);
});
fr.readAsArrayBuffer(data);
});
let is = Components.classes["@mozilla.org/io/arraybuffer-input-stream;1"]
.createInstance(Components.interfaces.nsIArrayBufferInputStream);
is.setData(arrayBuffer, 0, arrayBuffer.byteLength);
data = is;
}
await new Zotero.Promise(function (resolve, reject) {
var os = FileUtils.openSafeFileOutputStream(new FileUtils.File(path));
NetUtil.asyncCopy(data, os, function(inputStream, status) {
if (!Components.isSuccessCode(status)) {
reject(new Components.Exception("File write operation failed", status));
return;
}
resolve();
});
});
return deferred.promise;
};

View file

@ -519,7 +519,7 @@ Zotero.Translators = new function() {
Zotero.debug("Saving translator '" + metadata.label + "'");
Zotero.debug(metadata);
return Zotero.File.putContentsAsync(destFile, str).return(destFile);
return Zotero.File.putContentsAsync(destFile, str).then(() => destFile);
});
this.cacheInDB = function(fileName, metadataJSON, lastModifiedTime) {

View file

@ -83,6 +83,31 @@ describe("Zotero.File", function () {
});
describe("#putContentsAsync()", function () {
it("should save a text string", async function () {
var tmpDir = await getTempDirectory();
var destFile = OS.Path.join(tmpDir, 'test');
var str = 'A';
await Zotero.File.putContentsAsync(destFile, str);
assert.equal(await Zotero.File.getContentsAsync(destFile), str);
});
it("should save a Blob", async function () {
var srcFile = OS.Path.join(getTestDataDirectory().path, 'test.pdf');
var tmpDir = await getTempDirectory();
var destFile = OS.Path.join(tmpDir, 'test.pdf');
var blob = await File.createFromFileName(srcFile);
await Zotero.File.putContentsAsync(destFile, blob);
var destContents = await Zotero.File.getBinaryContentsAsync(destFile);
assert.equal(
await Zotero.File.getBinaryContentsAsync(srcFile),
destContents
);
assert.equal(destContents.substr(0, 4), '%PDF');
});
it("should save via .tmp file", function* () {
var tmpDir = yield getTempDirectory();
var destFile = OS.Path.join(tmpDir, 'test.txt')
@ -91,7 +116,7 @@ describe("Zotero.File", function () {
assert.isTrue(yield OS.File.exists(tmpFile));
yield Zotero.File.putContentsAsync(destFile, 'B');
assert.isFalse(yield OS.File.exists(tmpFile));
// Make sure .tmp file created when creating temp file was deleted too
// Make sure .tmp file was deleted
assert.isFalse(yield OS.File.exists(tmpFile + '.tmp'));
});
});