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:
parent
a08c3dee14
commit
a745cde2cf
1 changed files with 45 additions and 25 deletions
|
@ -446,8 +446,7 @@ 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
|
|
||||||
msg = "Server not found. Check your internet connection."
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
let listener = Cc[
|
||||||
|
"@mozilla.org/network/simple-stream-listener;1"
|
||||||
|
].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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
|
Loading…
Reference in a new issue