Search code examples
xulnsfilemanager

Firefox plugin to click button download a file and post it to another server


I have access a website that has a simple button (I dont own the site and dont have access to the source) to download a document. I am using the code below to execute this and it seems to work ok but is glitchy

Objective

  • I want to download the file

  • Post the file data to another site

Issues

  • Sometimes the document downloaded is large or simply there isnt a document present after clicking the button
    • Doesnt work on the same version of FF on different machines same OS

The code below

  Components.utils.import("resource://gre/modules/Downloads.jsm");
  Components.utils.import("resource://gre/modules/Task.jsm");

  window.content.location.href = "javascript:void download_document()";

  Task.spawn(function () {
    let list = yield Downloads.getList(Downloads.ALL);
    let downloads = yield list.getAll();
    setTimeout(function(d_before){
        Task.spawn(function(d_before) {
          let list = yield Downloads.getList(Downloads.ALL);
          let downloads = yield list.getAll();
          var file =  downloads[downloads.length-1];
          var parts = file.target.path.split('/');
          var document_name = parts[parts.length-1];

          // alert(document_name);
          var file = FileUtils.getFile("DfltDwnld", [document_name]);
          Components.utils.import("resource://gre/modules/NetUtil.jsm");
          NetUtil.asyncFetch(file, function(inputStream, status) {

            // alert("Fetching file");
            if (!Components.isSuccessCode(status)) {
              return;
            }
            var data =  NetUtil.readInputStreamToString(inputStream, inputStream.available());

            // alert("Reading file data");
            data = window.btoa(data);

            // alert("File data read");
            // alert(prefs.getCharPref("server_ip"));
            xmlhttp.open("POST",ht_server+"/import_document",true);
            xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xmlhttp.send("authentication_token="+prefs.getCharPref("api_key")
                +"&email="+prefs.getCharPref("email")
                +"&body="+encodeURIComponent(content.document.body.innerHTML)
                +"&document_name="+document_name
                +"&document_data="+encodeURIComponent(data));
            // alert("Finished");
          });
        }).then(null, Components.utils.reportError);
    },3000);
  }).then(null, Components.utils.reportError);

The code above is not complete for my solution but my main concern is that it does work on some machines and on others I get this error (when a document is downloaded)

NS_ERROR_NOT_AVAILABLE: Async version must be used nsHelperAppDlg.js:209:0
[Exception... "Component returned failure code: 0x80520001 (NS_ERROR_FILE_UNRECOGNIZED_PATH) [nsIFile.append]"  nsresult: "0x80520001 (NS_ERROR_FILE_UNRECOGNIZED_PATH)"  location: "JS frame :: resource://gre/modules/FileUtils.jsm :: FileUtils_getFile :: line 43"  data: no] Promise-backend.js:873:0
NS_ERROR_NOT_AVAILABLE: Async version must be used nsHelperAppDlg.js:209:0
[Exception... "Component returned failure code: 0x80520001 (NS_ERROR_FILE_UNRECOGNIZED_PATH) [nsIFile.append]"  nsresult: "0x80520001 (NS_ERROR_FILE_UNRECOGNIZED_PATH)"  location: "JS frame :: resource://gre/modules/FileUtils.jsm :: FileUtils_getFile :: line 43"  data: no] Promise-backend.js:873:0
A promise chain failed to handle a rejection. Did you forget to '.catch', or did you forget to 'return'?
See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise

Not being an expert in this I've not been able to resolve it

Can anyone give some advice?


Solution

  •   function download_and_post(){
    
          //simple version
    
          //button click or whatever that starts the download
          window.content.location.href = "javascript:void download_document()";
    
    
    
          var dJsm = Components.utils.import("resource://gre/modules/Downloads.jsm").Downloads;
          var tJsm = Components.utils.import("resource://gre/modules/Task.jsm").Task;
          var fuJsm = Components.utils.import("resource://gre/modules/FileUtils.jsm").FileUtils;
          var nsiPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
    
    
            var view = {
               onDownloadChanged: function (download) {
                  if (download.succeeded) {
                   var file = fuJsm.File(download.target.path);
                   NetUtil.asyncFetch(file, function(inputStream, status) {
                     if (!Components.isSuccessCode(status)) {
                      return;
                     }
                      var data =  NetUtil.readInputStreamToString(inputStream, inputStream.available());
                      btoa_data = window.btoa(data);
    
                      var xmlhttp = new XMLHttpRequest(); 
                      xmlhttp.open("POST","http://someserver.com",true);
                      xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                      xmlhttp.send(
                          "file_data="+encodeURIComponent(btoa_data)
                          +"&file_name="+ get_file_for_os(download.target.path)
                      );
                  });
                    tJsm.spawn(function () {
                       let list = yield dJsm.getList(Downloads.ALL);
                       list.removeView(view);
                    }).then(null, Components.utils.reportError); 
                  }
               }
            };
    
            tJsm.spawn(function () {
               let list = yield dJsm.getList(Downloads.ALL);
               list.addView(view);
            }).then(null, Components.utils.reportError);
      }
    
    
      function get_file_for_os(file){
          var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS; 
          if (osString == "Linux"){
              var document_name_no_path = file.split('/').pop();
          }else{
              var document_name_no_path= file.split("\\").pop();
          }
          return document_name_no_path;
      }
    

    This works on all platforms and sends the document name and data ;-)