写真公開プログラムver5の開発中。入力情報の一時保存の方法を調べてたら、Javascriptでファイルのダウンロードができるっぽいのでやってみた。
方法としては、aタグにdownload属性を追加していい感じに設定するといいらしい。
なので早速やってみた
const compressedData = pako.gzip(data);
// ダウンロード
const downloadURL = URL.createObjectURL(new Blob([compressedData], { type: 'application/gzip' }));
const downloadLink = document.createElement('a');
document.body.appendChild(downloadLink);
downloadLink.download = 'data.gz';
downloadLink.href = downloadURL;
downloadLink.click();
downloadLink.remove();
URL.revokeObjectURL(downloadURL);
dataには保存したい情報を入れておく。データはでかいのでpakoでgzip圧縮。
URL.createObjectURLで圧縮データをダウンロードするためのURLを作成。
aタグを作ってbodyに配置。downloadにファイル名を、hrefにcreateObjectURLの戻り値をセット。
それを.click()でクリックイベントを発火させるとダウンロード確認のダイアログが出る。
イベントを発火させたら、removeでaタグを削除してURL.revokeObjectURLでURLを削除して完了。
おまけ:ダウンロードしたファイルの復元。
const upload = (event: React.DragEvent) => {
event.stopPropagation();
event.preventDefault();
const uploadFiles = Array.from(event.dataTransfer.files) as File[];
if (/.gz$/.test(uploadFiles[0].name)) {
// 一時保存のリストア
const storeFile = uploadFiles[0];
const reader = new FileReader();
reader.onload = (result) => {
const decompressedData = new TextDecoder('utf-8')
.decode(pako.ungzip(new Uint8Array(result.target.result as ArrayBuffer)));
const restoreData: RestoreData = JSON.parse(decompressedData);
setPhotoList(restoreData.data);
};
reader.readAsArrayBuffer(storeFile);
}
}
<section className="upload">
<div
onDragEnter={(e: React.DragEvent) => { e.stopPropagation(); e.preventDefault(); }}
onDragOver={(e: React.DragEvent) => { e.stopPropagation(); e.preventDefault(); }}
onDrop={upload}
style={{ height: '10em', backgroundColor: '#cccccc' }}
/>
</section>
divのondropイベントハンドラでgzファイルのドラッグアンドドロップを受付。
FileReaderのreadAsArrayBufferで読み込んだデータをpakoでデコードしてstateに入れてReactにレンダリング要求して完了。