Come calcolare l’hash MD5 di un file usando javascript

C’è un modo per calcolare l’hash MD5 di un file prima del caricamento sul server usando Javascript?

Sebbene esistano implementazioni JS dell’algoritmo MD5, i browser più vecchi non sono in genere in grado di leggere i file dal filesystem locale .

L’ho scritto nel 2009. Che dire dei nuovi browser?

Con un browser che supporta FileAPI , * puoi * leggere il contenuto di un file – l’utente deve averlo selezionato, con un elemento o drag-and-drop. A partire da gennaio 2013, ecco come si impilano i principali browser:

  • FF 3.6 supporta FileReader , FF4 supporta ancora più funzionalità basate su file
  • Chrome ha supportato FileAPI dalla versione 7.0.517.41
  • Internet Explorer 10 supporta parzialmente FileAPI
  • Opera 11.10 ha supporto parziale per FileAPI
  • Safari – Non sono riuscito a trovare una buona fonte ufficiale per questo, ma questo sito suggerisce il supporto parziale da 5.1, pieno supporto per 6.0 . Un altro articolo riporta alcune incoerenze con le versioni precedenti di Safari

Ho creato una libreria che implementa l’MDD incrementale per eseguire l’hash di file di grandi dimensioni in modo efficiente. Fondamentalmente si legge un file in blocchi (per mantenere la memoria bassa) e lo si hash in modo incrementale. Hai un utilizzo di base ed esempi nel readme.

Tieni presente che hai bisogno di HTML5 FileAPI, quindi assicurati di verificarlo. C’è un esempio completo nella cartella di test.

https://github.com/satazor/SparkMD5

è abbastanza facile calcolare l’hash MD5 usando la funzione MD5 di CryptoJS e l’ API FileReader HTML5 . Il seguente frammento di codice mostra come puoi leggere i dati binari e calcolare l’hash MD5 da un’immagine che è stata trascinata nel tuo browser:

 var holder = document.getElementById('holder'); holder.ondragover = function() { return false; }; holder.ondragend = function() { return false; }; holder.ondrop = function(event) { event.preventDefault(); var file = event.dataTransfer.files[0]; var reader = new FileReader(); reader.onload = function(event) { var binary = event.target.result; var md5 = CryptoJS.MD5(binary).toString(); console.log(md5); }; reader.readAsBinaryString(file); }; 

Raccomando di aggiungere alcuni CSS per vedere l’area Drag & Drop:

 #holder { border: 10px dashed #ccc; width: 300px; height: 300px; } #holder.hover { border: 10px dashed #333; } 

Ulteriori informazioni sulla funzionalità Drag & Drop sono disponibili qui: File API e FileReader

Ho provato l’esempio in Google Chrome versione 32.

Devi usare FileAPI. È disponibile nell’ultima versione di FF e Chrome, ma non in IE9. Prendi qualsiasi implementazione di JD md5 suggerita sopra. Ho provato questo e abbandonato perché JS era troppo lento (minuti su file di immagine di grandi dimensioni). Potresti rivederlo se qualcuno riscrive MD5 usando array digitati.

Il codice sarebbe simile a questo:

 HTML:  JS (w JQuery) $("#file-dialog").change(function() { handleFiles(this.files); }); function handleFiles(files) { for (var i=0; i 

A prescindere dall’impossibilità di ottenere l’accesso al file system in JS, non darei alcuna fiducia in un checksum generato dal client. Quindi la generazione del checksum sul server è obbligatoria in ogni caso. – Tomalak 20 aprile 09 alle 14:05

Che è inutile nella maggior parte dei casi. Si desidera che l’MD5 sia calcolato sul lato client, in modo da poterlo confrontare con il codice ricalcolato sul lato server e concludere che il caricamento è andato storto se si sono differenziati. Ho avuto bisogno di farlo in applicazioni che lavorano con file di grandi dimensioni di dati scientifici, dove la ricezione di file non corretti era la chiave. I miei casi erano semplici, perché gli utenti avevano l’MD5 già calcolato dai loro strumenti di analisi dei dati, quindi dovevo solo chiederglielo con un campo di testo.

HTML5 + spark-md5 e Q

Supponendo che tu stia utilizzando un browser moderno (che supporta l’API file HTML5), ecco come si calcola l’ hash MD5 di un file di grandi dimensioni (verrà calcolato l’hash su blocchi variabili)

 function calculateMD5Hash(file, bufferSize) { var def = Q.defer(); var fileReader = new FileReader(); var fileSlicer = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; var hashAlgorithm = new SparkMD5(); var totalParts = Math.ceil(file.size / bufferSize); var currentPart = 0; var startTime = new Date().getTime(); fileReader.onload = function(e) { currentPart += 1; def.notify({ currentPart: currentPart, totalParts: totalParts }); var buffer = e.target.result; hashAlgorithm.appendBinary(buffer); if (currentPart < totalParts) { processNextPart(); return; } def.resolve({ hashResult: hashAlgorithm.end(), duration: new Date().getTime() - startTime }); }; fileReader.onerror = function(e) { def.reject(e); }; function processNextPart() { var start = currentPart * bufferSize; var end = Math.min(start + bufferSize, file.size); fileReader.readAsBinaryString(fileSlicer.call(file, start, end)); } processNextPart(); return def.promise; } function calculate() { var input = document.getElementById('file'); if (!input.files.length) { return; } var file = input.files[0]; var bufferSize = Math.pow(1024, 2) * 10; // 10MB calculateMD5Hash(file, bufferSize).then( function(result) { // Success console.log(result); }, function(err) { // There was an error, }, function(progress) { // We get notified of the progress as it is executed console.log(progress.currentPart, 'of', progress.totalParts, 'Total bytes:', progress.currentPart * bufferSize, 'of', progress.totalParts * bufferSize); }); } 
   

Per ottenere l’hash dei file, ci sono molte opzioni. Normalmente il problema è che è molto lento ottenere l’hash dei file di grandi dimensioni.

Ho creato una piccola libreria che ottiene l’hash dei file, con 64kb all’inizio del file e 64kb di fine.

Esempio dal vivo: http://marcu87.github.com/hashme/ e libreria: https://github.com/marcu87/hashme

C’è un paio di script là fuori su Internet per creare un hash MD5.

Quello di webtoolkit è buono, http://www.webtoolkit.info/javascript-md5.html

Sebbene, non credo che avrà accesso al filesystem locale in quanto tale accesso è limitato.

Con l’attuale HTML5 dovrebbe essere ansible calcolare l’hash md5 di un file binario, ma penso che il passo precedente sarebbe quello di convertire i dati banali di BlobBuilder in una stringa, sto provando a fare questo passo: ma non ho avuto successo.

Ecco il codice che ho provato: convertire un BlobBuilder in stringa, in Javascript HTML5

Non credo che ci sia un modo in javascript per accedere ai contenuti di un caricamento di file. Pertanto, non è ansible esaminare il contenuto del file per generare una sum MD5.

È comunque ansible inviare il file al server, che può quindi inviare una sum MD5 indietro o inviare il contenuto del file indietro .. ma questo è un sacco di lavoro e probabilmente non vale la pena per i vostri scopi.

Senza un plugin non puoi accedere a quei dati binari. Dovresti esaminare l’utilizzo di uno strumento di caricamento basato su Flash. Ho colleghi che hanno utilizzato SWFUpload , ma non so come accedere al contenuto del file stesso. Potrebbe essere necessario modificare il SWF stesso per consentire questo.