我發現,通過使用替代API的下載速度越來越快和UI更加敏感:
function downloadFromUrl(url, file, callback) {
var channel = chrome.Cc["@mozilla.org/network/io-service;1"]
.getService(chrome.Ci.nsIIOService)
.newChannel(url, 0, null);
var bstream = chrome.Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(chrome.Ci.nsIBinaryInputStream);
bstream.setInputStream(channel.open());
var fos = chrome.Cc["@mozilla.org/network/safe-file-output-stream;1"]
.createInstance(chrome.Ci.nsIFileOutputStream);
try {
fos.init(file, 0x04 | 0x08 | 0x10 | 0x20 | 0x40, 0600, 0); // see:https://developer.mozilla.org/en-US/docs/PR_Open#Parameters
var length = 0;
var size = 0;
while(size = bstream.available()) {
fos.write(bstream.readBytes(size), size);
length += size;
callback(length);
}
} finally {
if (fos instanceof chrome.Ci.nsISafeOutputStream) {
fos.finish();
} else {
fos.close();
}
}
}
我知道,這是一種原始的API,但它工作的方式比其它的方法更..
編輯:
我改進了上述功能,但它可能是太臃腫,這裏是它反正:
/**
* Downloads from a given url to a local file
* @param url url to download
* @param file local file
* @param callback called during the download, signature: callback(currentBytes)
* @returns downloadResult {contentType, error: false | ExceptionObject}
*/
function downloadFromUrl(url, file, callback) {
let result = {
contentType: null,
error: false
};
try {
let channel = chrome.Cc["@mozilla.org/network/io-service;1"]
.getService(chrome.Ci.nsIIOService)
.newChannel(url, 0, null);
let bstream = chrome.Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(chrome.Ci.nsIBinaryInputStream);
bstream.setInputStream(channel.open());
let fos = chrome.Cc["@mozilla.org/network/safe-file-output-stream;1"]
.createInstance(chrome.Ci.nsIFileOutputStream);
try {
// const values from https://developer.mozilla.org/en-US/docs/PR_Open#Parameters
const PR_RDWR = 0x04; // Open for reading and writing.
const PR_CREATE_FILE = 0x08; // If the file does not exist, the file is created. If the file exists, this flag has no effect.
const PR_APPEND = 0x10; // The file pointer is set to the end of the file prior to each write.
const PR_TRUNCATE = 0x20; // If the file exists, its length is truncated to 0.
const PR_SYNC = 0x40; // If set, each write will wait for both the file data and file status to be physically updated.
fos.init(file, PR_RDWR | PR_CREATE_FILE | PR_APPEND | PR_TRUNCATE | PR_SYNC, 0600, 0);
let length = 0;
let size = bstream.available();
while(size) {
fos.write(bstream.readBytes(size), size);
length += size;
callback(length);
size = bstream.available();
}
fos.flush();
result.contentType = channel.contentType;
} finally {
if (fos instanceof chrome.Ci.nsISafeOutputStream) {
fos.finish();
} else {
fos.close();
}
}
} catch (e) {
result.error = e;
}
return result;
}