ダウンロードして復号までの流れ
ファイルのダウンロード時にはlocation.
location.
ファイルをダウンロードする
XMLHttpRequestを使って暗号化済みのファイルをダウンロードします。responseTypeを指定することで,
XMLHttpRequestで従来よりよく使われるresponseTextは,
- あいうえお
とUTF-8で書かれたファイルを受信した場合,
リスト4 textとして受信する場合
req = new XMLHttpRequest;
req.open("GET", "test.txt", false);
req.send();
req.responseText.length; // 5 文字
リスト5 バイナリデータとして受信する場合
req = new XMLHttpRequest;
req.responseType = "arraybuffer";
req.open("GET", "test.txt", false);
req.send();
req.response.byteLength; // 15bytes
それに対して,req.
はリスト4のように5文字を示します。文字数とバイト数が一致しないと,
今までXMLHttpRequestを使ってバイナリファイルを扱うには,charset = x-user-defined
という文字コードを指定する方法がよく知られていました
特殊な文字コード指定を使うことで,
- 注8)
- XMLHttpRequestを使わない方法もあります。古いブラウザなど,
バイナリデータの受信に支障がある場合, サーバ側でバイナリデータをBase64エンコードして取り扱うのです。しかし, この方法ではファイルサイズが大きくなってしまいます。 - 注9)
- 実際にはもう少し複雑な手順が必要ですが,
詳細は省きます。
ファイルのダウンロードと復号
単純にXMLHttpRequestで巨大なファイルをダウンロードする場合,
この問題はサーバ側でファイルを分割してダウンロードすることで解決できます。問題は,
crypto-jsでは受信したデータを順次復号していくことが可能ですが,
ほかのブラウザでは動かないことになってしまうので,
リスト6 ダウンロード処理
function download(path, password, filename){
req = new XMLHttpRequest;
req.open("GET", "./files/" + path, true);
req.responseType = "arraybuffer";
req.onload = function(){
var buffer = req.response;
decode_arraybuffer(buffer, password, filename);
};
req.send("");
}
function objecturlready(url, filename){
var el;
if (/(gif|jpg|png)$/i.test(filename)) {
el = TB("img", {title: filename, alt: filename, src: url});
} else {
el = TB("a", {href: url, download: filename}, "Click here to save file");
}
document.getElementById("result").appendChild(el);
}
function decode_arraybuffer(ab, password, filename) {
var dec = new StreamDecryptor(password);
dec.decorder = null;
var wordarray = CryptoJS.lib.WordArray.create( ab );
dec.process(wordarray);
dec.process();
var isImage = /(gif|jpg|png)$/i.test(filename);
var suffix = filename.match(/([^.]*?)$/);
suffix = suffix ? suffix[1].toLowerCase() : "";
var mimetype = isImage ? { type: "image/"+suffix}
: { type: "application/octet-stream"};
if (window.requestFileSystem) {
var file = new TempFile();
file.onready = function(){
file.write( new Blob(dec.result) );
setTimeout(function(){
objecturlready(file.toURL(), filename);
}, 100);
};
} else {
// Safari does not support create blob from typed array
var isBuggyBrowser = (new Blob([new Uint8Array()]).size > 0 ) ? true : false;
var blob = isBuggyBrowser
? new Blob(dec.result.map(function(v){ return v.buffer }), mimetype)
: new Blob(dec.result, mimetype);
var objectURL = (
window.URL || window.webkitURL || dataURLsim
).createObjectURL(blob);
setTimeout(function(){
objecturlready(objectURL, filename);
}, 0);
}
}