Javascript を使用してサーバーにアップロードする前に、ファイルの MD5 ハッシュを計算する方法はありますか?
12 に答える
MD5 アルゴリズムのJS 実装はありますが、古いブラウザは通常、ローカル ファイルシステムからファイルを読み取ることができません。
私は 2009 年にそれを書きました。では、新しいブラウザーはどうでしょうか。
FileAPIをサポートするブラウザーを使用すると、ファイルの内容を読み取ることができます。ユーザーは、<input>
要素またはドラッグ アンド ドロップのいずれかを使用してファイルを選択する必要があります。2013 年 1 月現在、主なブラウザーの違いは次のとおりです。
- FF 3.6 はFileReaderをサポートし、FF4 はさらに多くのファイルベースの機能をサポートします
- Chrome はバージョン 7.0.517.41から FileAPI をサポートしています
- Internet Explorer 10 はFileAPI を部分的にサポートしています
- Opera 11.10 はFileAPI を部分的にサポートしています
- Safari - 適切な公式ソースが見つかりませんでしたが、このサイトでは 5.1 から部分的にサポートされ、6.0 では完全にサポートされることを示唆しています。別の記事では、古い Safari バージョンとのいくつかの不一致が報告されています
どのように?
CryptoJSの MD5 関数を使用するBenny Neugebauer による以下の回答を参照してください。
大きなファイルを効率的にハッシュするために、増分 md5 を実装するライブラリを作成しました。基本的に、ファイルをチャンクで読み取り (メモリを低く抑えるため)、段階的にハッシュします。readme に基本的な使用方法と例が記載されています。
HTML5 FileAPI が必要なので、必ず確認してください。test フォルダに完全な例があります。
MD5 ハッシュは、CryptoJS の MD5 関数とHTML5 FileReader APIを使用して簡単に計算できます。次のコード スニペットは、ブラウザにドラッグされた画像からバイナリ データを読み取り、MD5 ハッシュを計算する方法を示しています。
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);
};
ドラッグ アンド ドロップ領域を表示するには、いくつかの CSS を追加することをお勧めします。
#holder {
border: 10px dashed #ccc;
width: 300px;
height: 300px;
}
#holder.hover {
border: 10px dashed #333;
}
ドラッグ アンド ドロップ機能の詳細については、こちらをご覧ください: File API & FileReader
Google Chrome バージョン 32 でサンプルをテストしました。
FileAPI を使用する必要があります。最新の FF と Chrome では利用できますが、IE9 では利用できません。上記で提案された md5 JS 実装を取得します。私はこれを試してみましたが、JS が遅すぎる (大きな画像ファイルでは数分) ため、放棄しました。誰かが型付き配列を使用して MD5 を書き直した場合、再訪する可能性があります。
コードは次のようになります。
HTML:
<input type="file" id="file-dialog" multiple="true" accept="image/*">
JS (w JQuery)
$("#file-dialog").change(function() {
handleFiles(this.files);
});
function handleFiles(files) {
for (var i=0; i<files.length; i++) {
var reader = new FileReader();
reader.onload = function() {
var md5 = binl_md5(reader.result, reader.result.length);
console.log("MD5 is " + md5);
};
reader.onerror = function() {
console.error("Could not read the file");
};
reader.readAsBinaryString(files.item(i));
}
}
JS でファイル システムにアクセスできないことを除けば、私はクライアントが生成したチェックサムをまったく信用しません。したがって、サーバーでチェックサムを生成することは、いずれの場合も必須です。— トマラク 2009 年 4 月 20 日 14:05
ほとんどの場合、これは役に立ちません。MD5 をクライアント側で計算して、サーバー側で再計算されたコードと比較し、それらが異なる場合はアップロードが失敗したと判断できるようにします。破損していないファイルを受信することが重要な科学データの大規模なファイルを扱うアプリケーションでは、これを行う必要がありました。私の場合は単純で、ユーザーはデータ分析ツールから MD5 を計算済みだったので、テキスト フィールドを使って質問するだけで済みました。
ファイルのハッシュを取得するには、多くのオプションがあります。通常、問題は、大きなファイルのハッシュを取得するのが非常に遅いことです。
ファイルの先頭の 64kb と末尾の 64kb を使用して、ファイルのハッシュを取得する小さなライブラリを作成しました。
実際の例: http://marcu87.github.com/hashme/およびライブラリ: https://github.com/marcu87/hashme
インターネット上には、MD5 ハッシュを作成するためのスクリプトがいくつかあります。
webtoolkit のものは良いです、http://www.webtoolkit.info/javascript-md5.html
ただし、アクセスが制限されているため、ローカルファイルシステムにアクセスできるとは思いません。
あなたが今までに良い解決策を見つけたことを願っています. そうでない場合、以下のソリューションはjs-spark-md5に基づく ES6 promise 実装です。
import SparkMD5 from 'spark-md5';
// Read in chunks of 2MB
const CHUCK_SIZE = 2097152;
/**
* Incrementally calculate checksum of a given file based on MD5 algorithm
*/
export const checksum = (file) =>
new Promise((resolve, reject) => {
let currentChunk = 0;
const chunks = Math.ceil(file.size / CHUCK_SIZE);
const blobSlice =
File.prototype.slice ||
File.prototype.mozSlice ||
File.prototype.webkitSlice;
const spark = new SparkMD5.ArrayBuffer();
const fileReader = new FileReader();
const loadNext = () => {
const start = currentChunk * CHUCK_SIZE;
const end =
start + CHUCK_SIZE >= file.size ? file.size : start + CHUCK_SIZE;
// Selectively read the file and only store part of it in memory.
// This allows client-side applications to process huge files without the need for huge memory
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
};
fileReader.onload = e => {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) loadNext();
else resolve(spark.end());
};
fileReader.onerror = () => {
return reject('Calculating file checksum failed');
};
loadNext();
});
現在の HTML5 では、バイナリ ファイルの md5 ハッシュを計算できるはずですが、その前のステップは、バイナリ データ BlobBuilder を文字列に変換することだと思います。このステップを実行しようとしていますが、成功していません。
私が試したコードは次のとおりです: Converting a BlobBuilder to string, in HTML5 Javascript
ファイルアップロードのコンテンツにアクセスする方法がjavascriptにあるとは思いません。そのため、ファイルの内容を調べて MD5 サムを生成することはできません。
ただし、ファイルをサーバーに送信すると、サーバーは MD5 サムを送信したり、ファイルの内容を送信したりできます..