New implementation of a download function #2216

This resolves a problem where, in certain scenarios,
Zotero.file.download throws an exception even though file is
successfully downloaded.

Furthermore this new download function should be more memory-efficient,
improving performance when dealing with large files.
This commit is contained in:
Tom Najdek 2021-10-02 00:34:51 +02:00
parent a08c3dee14
commit a745cde2cf
No known key found for this signature in database
GPG key ID: EEC61A7B4C667D77

View file

@ -445,9 +445,8 @@ Zotero.File = new function(){
}); });
}); });
}; };
this.download = async function (uri, path) {
this.download = Zotero.Promise.coroutine(function* (uri, path) {
var uriStr = uri.spec || uri; var uriStr = uri.spec || uri;
Zotero.debug(`Saving ${uriStr} to ${path.pathQueryRef || path}`); Zotero.debug(`Saving ${uriStr} to ${path.pathQueryRef || path}`);
@ -459,31 +458,52 @@ Zotero.File = new function(){
} }
var deferred = Zotero.Promise.defer(); var deferred = Zotero.Promise.defer();
NetUtil.asyncFetch(uri, function (is, status, request) { const uri_ = NetUtil.ioService.newURI(uri);
if (!Components.isSuccessCode(status)) { const inputChannel = NetUtil.ioService.newChannelFromURI(uri_);
Zotero.logError(status); const outputChannel = FileUtils.openSafeFileOutputStream(new FileUtils.File(path));
let msg = Zotero.getString('sync.error.checkConnection'); const pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
switch (status) { pipe.init(true, true, 0, 0xffffffff, null);
case 2152398878:
// TODO: Localize let listener = Cc[
msg = "Server not found. Check your internet connection." "@mozilla.org/network/simple-stream-listener;1"
break; ].createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest(request) {
// NOTE: This noop callback is required, do not remove.
},
onStopRequest(request, status) {
const responseStatus = 'responseStatus' in request ? request.responseStatus : null;
pipe.outputStream.close();
if (!Components.isSuccessCode(status)) {
Zotero.logError(status);
let msg = Zotero.getString('sync.error.checkConnection');
switch (status) {
case 2152398878:
// TODO: Localize
msg = "Server not found. Check your internet connection."
break;
}
deferred.reject(new Error(msg));
return;
}
if (responseStatus != 200) {
let msg = `Download failed with response code ${responseStatus}`;
Zotero.logError(msg);
deferred.reject(new Error(msg));
return;
} }
deferred.reject(new Error(msg));
return;
} }
if (request.responseStatus != 200) {
let msg = `Download failed with response code ${request.responseStatus}`;
Zotero.logError(msg);
deferred.reject(new Error(msg));
return;
}
deferred.resolve(is);
}); });
var is = yield deferred.promise;
yield Zotero.File.putContentsAsync(path, is); NetUtil.asyncCopy(pipe.inputStream, outputChannel, function(aResult) {
}); deferred.resolve();
});
inputChannel.asyncOpen(listener, null);
return deferred.promise;
};
/** /**
* Rename file within its parent directory * Rename file within its parent directory