views:

398

answers:

5

What I need to do is provide a file browser box on a web page where a user selects a file from their computer and, through javascript (or flash if necessary), some sort of Hash is returned such as CRC, MD5 or SHA1. I would prefer not to have to upload the entire file to the web server, as I expect some rather large files to be used in this.

Basically I am making a script that associates these values with META data of sorts, allowing the files to be identified without having to be uploaded completely.

Any idea how I would go about doing this? It'd be easy for me to do it on the server side, but, as I said, there will be some rather large files checked and I don't want to eat up too much of the server's bandwidth.

A: 

Browsers (i.e. JavaScript) cannot access the local file system, period. If they could, it would be a security nightmare.

Diodeus
But then how do Flash Uploaders work? :S
Stephen Belanger
A: 

This is not possible with Javascript because of there is no access to the file system. I know this can be done with Silverlight. Perhaps someone with flash experience can answer.

BC
+4  A: 

You can do it with Flash, provided that the user has Flash Player 10.

Here is a tutorial

Also: Reading and writing local files in FP10

euge1979
Wow isn't this like really dangerous?
Luca Matteis
The dialog box can only be triggered by user interaction (i.e. click)Lee Brimelow discusses it in more detail here - http://theflashblog.com/?p=423
euge1979
ok... I dont get flash but anyway +1
Luca Matteis
+1  A: 

This is traditionally not possible with JavaScript, but it may be if the W3 File Upload spec ever catches on.

A variant is available in Firefox 3:

var content= input.files[0].getAsBinary();

For other browsers you would have to fall back to Flash and/or server-side hashing.

Here's a bonus JS implementation of SHA-1 for you:

function sha_hexdigest(bytes) {
  var digest= sha_bytes(sha_calculate(sha_ints(bytes), bytes.length*8));
  var digits= '0123456789abcdef';
  var hex= '';
  for (var i= 0; i<digest.length; i++) {
    var c= digest.charCodeAt(i);
    hex+= digits.charAt((c>>4)&0xF) + digits.charAt(c&0xF);
  }
  return hex;
}

function sha_ints(bytes) {
  while (bytes.length%4!=0)
    bytes+= '\x00';
  var ints= new Array();
  for (var i= 0; i<bytes.length; i+= 4) {
    ints[ints.length]= (
      (bytes.charCodeAt(i)&0xFF)<<24 | (bytes.charCodeAt(i+1)&0xFF)<<16 |
      (bytes.charCodeAt(i+2)&0xFF)<<8 | (bytes.charCodeAt(i+3)&0xFF)
    ); }
  return ints;
}

function sha_bytes(ints) {
  var bytes= '';
  for (var i= 0; i<ints.length; i++)
    bytes+= String.fromCharCode((ints[i]>>24)&0xFF, (ints[i]>>16)&0xFF, (ints[i]>>8)&0xFF, ints[i]&0xFF)
  return bytes;
}

function sha_calculate(ints, bitn) {
  while (ints.length*32<=bitn) ints[ints.length]= 0;
  ints[ints.length-1]|= 1<<(31-bitn%32)
  while (ints.length%16!=14) ints[ints.length]= 0;
  ints[ints.length]= Math.floor(bitn/0x100000000);
  ints[ints.length]= bitn&0xFFFFFFFF;

  var h0= 1732584193, h1= -271733879, h2= -1732584194, h3= 271733878, h4= -1009589776;
  var a, b, c, d, e, f, k, temp, w= new Array(80);
  for(var inti= 0; inti<ints.length; inti+= 16) {
    a= h0; b= h1; c= h2; d= h3; e= h4;
    for (var i= 0; i<16; i++) w[i]= ints[inti+i];
    for (; i<80; i++) w[i]= sha_rol(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);

    for(var i= 0; i<80; i++) {
      switch (Math.floor(i/20)) {
        case 0: f= sha_add(1518500249, (b & c) | ((~b) & d)); break;
        case 1: f= sha_add(1859775393, b ^ c ^ d); break;
        case 2: f= sha_add(-1894007588, (b & c) | (b & d) | (c & d)); break;
        case 3: f= sha_add(-899497514, b ^ c ^ d); break;
      }
      temp= sha_add( sha_add(sha_rol(a, 5), w[i]), sha_add(e, f) );
      e= d; d= c; c= b; b= a; a= temp;
      c= sha_rol(c, 30);
    }

    h0= sha_add(h0, a); h1= sha_add(h1, b); h2= sha_add(h2, c); h3= sha_add(h3, d); h4= sha_add(h4, e);
  }
  return new Array(h0, h1, h2, h3, h4);
}

function sha_add(a, b) {
  var lsw= (a&0xFFFF) + (b&0xFFFF);
  var msw= (a>>16) + (b>>16) + (lsw>>16);
  return (msw<<16) | (lsw&0xFFFF);
}

function sha_rol(n, bits) {
  return (n<<bits) | (n>>>(32-bits));
}
bobince
Not going to credit whoever wrote that SHA-1 implementation?
Dustin Fineout
As far as I'm aware, it's mine. It's nabbed from a years-old project which I only foggily remember now, but it certainly looks like my style at the time.
bobince
Excellent! I just recently wrote a JS implementation myself. I would suggest indicating yourself as the author when that is the case, otherwise it looks like flagrant plagiarism.
Dustin Fineout
A: 

With HTML5 File API, you can read files in local computer, have a good at my solution: Generate SHA1 File Checksum Using HTML5 File API in Javascript

Ke