写真公開プログラム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にレンダリング要求して完了。