mozilla

Revision 376751 of Downloading Files

  • Revision slug: Code_snippets/Downloading_Files
  • Revision title: Downloading Files
  • Revision id: 376751
  • Created:
  • Creator: ignisvulpis
  • Is current revision? No
  • Comment

Revision Content

Downloading files

To download a file, create an instance of {{ Interface("nsIWebBrowserPersist") }} and call its {{ Ifmethod("nsIWebBrowserPersist", "saveURI") }} method, passing it a URL to download and an {{ Interface("nsIFile") }} instance representing the local file name/path. 

Cu.import("chrome://gre/modules/PrivateBrowsingUtils.jsm");

const WebBrowserPersist = Components.Constructor("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                                                 "nsIWebBrowserPersist");

var persist = WebBrowserPersist();

var targetFile = Services.dirsvc.get("Desk", Ci.nsIFile);
targetFile.append("file.bin");

// Obtain the privacy context of the browser window that the URL
// we are downloading comes from. If, and only if, the URL is not
// related to a window, null should be used instead.
var privacy = PrivateBrowsingUtils.privacyContextFromWindow(urlSourceWindow);

persist.persistFlags = persist.PERSIST_FLAGS_FROM_CACHE
                     | persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;

persist.saveURI(uriToSave, null, null, null, "", targetFile, privacy);

If you don't need detailed progress information, you might be happier with {{ Interface("nsIDownloader") }}.

Downloading Binary Files with a Progress Listener

To download a binary file with custom progress listener:

Cu.import("chrome://gre/modules/PrivateBrowsingUtils.jsm");

const WebBrowserPersist = Components.Constructor("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                                                 "nsIWebBrowserPersist");

var persist = WebBrowserPersist();

var targetFile = Services.dirsvc.get("Desk", Ci.nsIFile);
targetFile.append("file.bin");

var obj_URI = Services.io.newURI(aURLToDownload, null, null);

// Obtain the privacy context of the browser window that the URL
// we are downloading comes from. If, and only if, the URL is not
// related to a window, null should be used instead.
var privacy = PrivateBrowsingUtils.privacyContextFromWindow(aURLSourceWindow);

var progressElement = document.getElementById("progress_element");
persist.progressListener = {
  onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {
    var percentComplete = Math.round((aCurTotalProgress / aMaxTotalProgress) * 100);
    progressElement.textContent = percentComplete +"%";
  },
  onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
    // do something
  }
}
persist.saveURI(obj_URI, null, null, null, "", targetFile, privacy);

Downloading files that require credentials

Before calling {{ Ifmethod("nsIWebBrowserPersist", "saveURI") }}, you need to set the progressListener property of the {{ Interface("nsIWebBrowserPersist") }} instance to an object that implements {{ Interface("nsIAuthPrompt") }}. Normally, {{ Interface("nsIAuthPrompt") }} expects a prompt to be displayed so the user can enter credentials, but you can return a username and password credentials directly without prompting the user. If you want to open a login prompt, you can use the default prompt by calling the window watcher's getNewAuthPrompter() method.

Cu.import("chrome://gre/modules/PrivateBrowsingUtils.jsm");

const WebBrowserPersist = Components.Constructor("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                                                 "nsIWebBrowserPersist");

var persist = WebBrowserPersist();

// Obtain the privacy context of the browser window that the URL
// we are downloading comes from. If, and only if, the URL is not
// related to a window, null should be used instead.
var privacy = PrivateBrowsingUtils.privacyContextFromWindow(urlSourceWindow);

var hardCodedUserName = "ericjung";
var hardCodedPassword = "foobar";
persist.progressListener = {
  QueryInterface: XPCOMUtils.generateQI(["nsIAuthPrompt"]),

  // implements nsIAuthPrompt
  prompt: function(dialogTitle, text, passwordRealm, savePassword, defaultText, result) {
    result.value = hardCodedPassword;
    return true;
  },
  promptPassword: function(dialogTitle, text, passwordRealm, savePassword, pwd) {
    pwd.value = hardCodedPassword;
    return true;
  },
  promptUsernameAndPassword: function(dialogTitle, text, passwordRealm, savePassword, user, pwd) {
    user.value = hardCodedUserName;
    pwd.value = hardCodedPassword;    
    return true;
  }
};

persist.saveURI(urlToSave, null, null, null, "", nsFileInstance, privacy);

The above is going to give you errors about missing {{ Interface("nsIDownloadProgressListener") }} methods, so you should implement that as well. For example, with empty dummy methods if you are not interested about the progress.

Instead of using QI like above, you can also implement {{ Interface("nsIInterfaceRequestor") }} and return {{ Interface("nsIAuthPrompt") }} from there, like {{ Interface("nsIWebBrowserPersist") }}.progressListener documentation suggests.

Downloading Images

Sample function for fetching an image file from a URL.

// This function is for fetching an image file from a URL. 
// Accepts a URL and returns the file. 
// Returns empty if the file is not found (with an 404 error for instance). 
// Tried with .jpg, .ico, .gif (even .html).

function GetImageFromURL(url) { 
  var ioserv = Components.classes["@mozilla.org/network/io-service;1"] 
               .getService(Components.interfaces.nsIIOService); 
  var channel = ioserv.newChannel(url, 0, null); 
  var stream = channel.open(); 

  if (channel instanceof Components.interfaces.nsIHttpChannel && channel.responseStatus != 200) { 
    return ""; 
  }

  var bstream = Components.classes["@mozilla.org/binaryinputstream;1"] 
                .createInstance(Components.interfaces.nsIBinaryInputStream); 
  bstream.setInputStream(stream); 

  var size = 0; 
  var file_data = ""; 
  while(size = bstream.available()) { 
    file_data += bstream.readBytes(size); 
  } 

  return file_data; 
}

See also

Revision Source

<h3 id="Downloading_files" name="Downloading_files">Downloading files</h3>
<p>To download a file, create an instance of {{ Interface("nsIWebBrowserPersist") }} and call its {{ Ifmethod("nsIWebBrowserPersist", "saveURI") }} method, passing it a URL to download and an {{ Interface("nsIFile") }} instance representing the local file name/path.&nbsp;</p>
<pre class="brush: js">
Cu.import("chrome://gre/modules/PrivateBrowsingUtils.jsm");

const WebBrowserPersist = Components.Constructor("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                                                 "nsIWebBrowserPersist");

var persist = WebBrowserPersist();

var targetFile = Services.dirsvc.get("Desk", Ci.nsIFile);
targetFile.append("file.bin");

// Obtain the privacy context of the browser window that the URL
// we are downloading comes from. If, and only if, the URL is not
// related to a window, null should be used instead.
var privacy = PrivateBrowsingUtils.privacyContextFromWindow(urlSourceWindow);

persist.persistFlags = persist.PERSIST_FLAGS_FROM_CACHE
                     | persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;

persist.saveURI(uriToSave, null, null, null, "", targetFile, privacy);</pre>
<p>If you don't need detailed progress information, you might be happier with {{ Interface("nsIDownloader") }}.</p>
<h4 id="Downloading_Binary_Files_with_a_Progress_Listener" name="Downloading_Binary_Files_with_a_Progress_Listener">Downloading Binary Files with a Progress Listener</h4>
<p>To download a binary file with custom progress listener:</p>
<pre class="brush: js">
Cu.import("chrome://gre/modules/PrivateBrowsingUtils.jsm");

const WebBrowserPersist = Components.Constructor("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                                                 "nsIWebBrowserPersist");

var persist = WebBrowserPersist();

var targetFile = Services.dirsvc.get("Desk", Ci.nsIFile);
targetFile.append("file.bin");

var obj_URI = Services.io.newURI(aURLToDownload, null, null);

// Obtain the privacy context of the browser window that the URL
// we are downloading comes from. If, and only if, the URL is not
// related to a window, null should be used instead.
var privacy = PrivateBrowsingUtils.privacyContextFromWindow(aURLSourceWindow);

var progressElement = document.getElementById("progress_element");
persist.progressListener = {
  onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {
    var percentComplete = Math.round((aCurTotalProgress / aMaxTotalProgress) * 100);
    progressElement.textContent = percentComplete +"%";
  },
  onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
    // do something
  }
}
persist.saveURI(obj_URI, null, null, null, "", targetFile, privacy);
</pre>
<h4 id="Downloading_files_that_require_credentials" name="Downloading_files_that_require_credentials">Downloading files that require credentials</h4>
<p>Before calling {{ Ifmethod("nsIWebBrowserPersist", "saveURI") }}, you need to set the <code>progressListener</code> property of the {{ Interface("nsIWebBrowserPersist") }} instance to an object that implements {{ Interface("nsIAuthPrompt") }}. Normally, {{ Interface("nsIAuthPrompt") }} expects a prompt to be displayed so the user can enter credentials, but you can return a username and password credentials directly without prompting the user. If you want to open a login prompt, you can use the default prompt by calling the window watcher's <code>getNewAuthPrompter()</code> method.</p>
<pre class="brush: js">
Cu.import("chrome://gre/modules/PrivateBrowsingUtils.jsm");

const WebBrowserPersist = Components.Constructor("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
                                                 "nsIWebBrowserPersist");

var persist = WebBrowserPersist();

// Obtain the privacy context of the browser window that the URL
// we are downloading comes from. If, and only if, the URL is not
// related to a window, null should be used instead.
var privacy = PrivateBrowsingUtils.privacyContextFromWindow(urlSourceWindow);

var hardCodedUserName = "ericjung";
var hardCodedPassword = "foobar";
persist.progressListener = {
  QueryInterface: XPCOMUtils.generateQI(["nsIAuthPrompt"]),

  // implements nsIAuthPrompt
  prompt: function(dialogTitle, text, passwordRealm, savePassword, defaultText, result) {
    result.value = hardCodedPassword;
    return true;
  },
  promptPassword: function(dialogTitle, text, passwordRealm, savePassword, pwd) {
    pwd.value = hardCodedPassword;
    return true;
  },
  promptUsernameAndPassword: function(dialogTitle, text, passwordRealm, savePassword, user, pwd) {
    user.value = hardCodedUserName;
    pwd.value = hardCodedPassword;    
    return true;
  }
};

persist.saveURI(urlToSave, null, null, null, "", nsFileInstance, privacy);
</pre>
<p>The above is going to give you errors about missing {{ Interface("nsIDownloadProgressListener") }} methods, so you should implement that as well. For example, with empty dummy methods if you are not interested about the progress.</p>
<p>Instead of using QI like above, you can also implement {{ Interface("nsIInterfaceRequestor") }} and return {{ Interface("nsIAuthPrompt") }} from there, like {{ Interface("nsIWebBrowserPersist") }}.<code>progressListener </code>documentation suggests.</p>
<h3 id="Downloading_Images" name="Downloading_Images">Downloading Images</h3>
<p>Sample function for fetching an image file from a URL.</p>
<pre class="brush: js">
// This function is for fetching an image file from a URL. 
// Accepts a URL and returns the file. 
// Returns empty if the file is not found (with an 404 error for instance). 
// Tried with .jpg, .ico, .gif (even .html).

function GetImageFromURL(url) { 
  var ioserv = Components.classes["@mozilla.org/network/io-service;1"] 
               .getService(Components.interfaces.nsIIOService); 
  var channel = ioserv.newChannel(url, 0, null); 
  var stream = channel.open(); 

  if (channel instanceof Components.interfaces.nsIHttpChannel &amp;&amp; channel.responseStatus != 200) { 
    return ""; 
  }

  var bstream = Components.classes["@mozilla.org/binaryinputstream;1"] 
                .createInstance(Components.interfaces.nsIBinaryInputStream); 
  bstream.setInputStream(stream); 

  var size = 0; 
  var file_data = ""; 
  while(size = bstream.available()) { 
    file_data += bstream.readBytes(size); 
  } 

  return file_data; 
}
</pre>
<h3 id="See_also" name="See_also">See also</h3>
<ul>
  <li>{{ Interface("nsIDownloadProgressListener") }}</li>
  <li><a href="/en/Code_snippets/Miscellaneous#Saving_the_current_web_page_to_a_local_file" title="en/Code_snippets/Miscellaneous#Saving_the_current_web_page_to_a_local_file">Saving the current web page to a local file</a></li>
  <li><a href="/en/Code_snippets/Miscellaneous#Saving_an_arbitrary_URL_to_a_local_file" title="en/Code_snippets/Miscellaneous#Saving_an_arbitrary_URL_to_a_local_file">Saving an arbitrary URL to a local file</a></li>
  <li><a class="internal" href="/En/Code_snippets/Customizing_the_download_progress_bar" title="En/Code snippets/Customizing the download progress bar">Customizing the download progress bar appearance</a></li>
</ul>
Revert to this revision