I have a list of file URLs. For each URL, I need to get the corresponding file size, without downloading the file (it could be a large file). How can I do it in Javascript? Thanks!
The idea is to use HTTP HEAD
request and then look at Content-Length
response header. HEAD requests always receive just headers and no response body, so no actual data will get downloaded. Here is a sample HEAD request:
The concept above is simple, however if you just go ahead and try to implement it, you may encounter the following problems:
If you run this code with Synchronous XMLHttpRequest, Chrome may try to scare you with the following warning message, displayed in the development console:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.
Just ignore that message b/c the end user will never see it. So here is the code:
function getFileSize(url)
{
var fileSize = '';
var http = new XMLHttpRequest();
http.open('HEAD', url, false); // false = Synchronous
http.send(null); // it will stop here until this http request is complete
// when we are here, we already have a response, b/c we used Synchronous XHR
if (http.status === 200) {
fileSize = http.getResponseHeader('content-length');
console.log('fileSize = ' + fileSize);
}
return fileSize;
}
Well, for ASYNC XHR we should not be even having that function getFileSize(url)
b/c when that function ends, the resulting fileSize is not ready yet :) Welcome to semantics of ASYNC JavaScript. Anyways, love it or hate it, here comes the ASYNC code:
function getFileSize(url)
{
var fileSize = '';
var http = new XMLHttpRequest();
http.open('HEAD', url, true); // true = Asynchronous
http.onreadystatechange = function() {
if (this.readyState == this.DONE) {
if (this.status === 200) {
fileSize = this.getResponseHeader('content-length');
console.log('fileSize = ' + fileSize);
//
// ok here is the only place in the code where we have our request result and file size ...
// the problem is that here we are in the middle of anonymous function nested into another function and it does not look pretty
// this stupid ASYNC pattern makes me hate Javascript even more than I already hate it :)
//
//
}
}
};
http.send(); // it will submit request and jump to the next line immediately, without even waiting for request result b/c we used ASYNC XHR call
return ('At this moment, we do not even have Request Results b/c we used ASYNC call to follow with stupid JavaScript patterns');
}
If your Javascript resides in the webpage loaded from mydomain.com
, and that script tries to use XMLHttpRequest to get access to some external domain like externalsite.com
, any modern browser will stop that request (b/c of the same origin policy) and throw an error message. Here is the error from Chrome:
XMLHttpRequest cannot load http://externalsite.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mydomain.com' is therefore not allowed access.
How to solve that problem? Well, maybe the server that hosts the file you are sizing - maybe that server allows cross domain requests. If not, you could try to use JSONP or some 3rd party function like GM_xmlhttpRequest
or a library like xdomain: A library that makes cross-origin requests in all browsers, back to IE8, really easy(I hope so).
I would appreciate if someone with more JavaScript knowledge than me would provide better solution to Cross Site problem, better explanation and better code examples. Please feel free to post your answers! Thanks!
FavScripts.com is a free tool to save your favorite scripts and commands, then quickly find and copy-paste your commands with just few clicks.
Boost your productivity with FavScripts.com!