2014-10-29 52 views
1

我有一個難以調試的問題,我需要在後臺下載很多(〜400)相當小(〜3-4mb)的文件Firefox的插件sdk API。Firefox UI在使用Addon SDK API下載許多文件時變得無響應

我使用舊的API(nsIWebBrowserPersist),以及新的API(Downloads.jsm)(簡稱代碼)嘗試:

Task.spawn(function() {     
    for (var i = 0; i < documents.length; i++) { 
    var url = ...; 
    var file = ...; 

    let download = yield Downloads.createDownload({ 
     source: url, 
     target: file, 
    }); 

    yield download.start(); 
    yield download.finalize(); 
    } 
}); 

但是UI一段時間後變得奇慢無比,我嘗試使用相同的文件並覆蓋它,因爲我的第一個猜測是隨着時間的推移積累的windows文件句柄,但它沒有幫助。它似乎與系統性能沒有關係,它在失敗5分鐘後有時也在同一臺機器上工作。

使用firefox sdk api下載大量文件是否存在已知問題,或者我做錯了什麼?

回答

1

我發現,通過使用替代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; 
}