はじめに
モダンブラウザならJavaScriptでファイルダウンロード処理を実現することができます。SPA(シングルページアプリケーション)など、クライアント側にデータを持つようなアプリケーションであればサーバアクセスなしにメモリの内容からファイルを生成してダウンロードさせることができます。
実装方法
やり方は
- リンクのHTML5のdownload属性を使用してダウンロードファイル名を設定
- File APIのBlobを使用してデータを作成
-
window.URL.createObjectURL
でBlobからURLを生成しそれをリンク先に設定
とするだけです。これでChromeとFireFoxはいけます(download属性のブラウザ実装状況を見るとを見ると、試せていないですがEdgeとOperaもいけそう)。加えてIEをサポートする場合は、IE10/11であればwindow.navigator.msSaveBlob(またはmsSaveOrOpenBlob)
を使うことで同様のことができます(IE9以下はBlobが使えないため対応できません)。Safariに関してはまた別の方法で対応することができるようで、saveAsのpolyfillであるFileSaver.jsではSafariにも対応している模様。実装はこのあたり。
サンプルコード
下記はChrome/FireFox/IE11で動作確認したサンプルコードになります。「ダウンロード」リンクをクリックすると「あいうえお」と書かれたテキストファイル(test.txt)がダウンロードされます。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Download Sample</title>
</head>
<body>
<script type='text/javascript'>
function handleDownload() {
var content = 'あいうえお';
var blob = new Blob([ content ], { "type" : "text/plain" });
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blob, "test.txt");
// msSaveOrOpenBlobの場合はファイルを保存せずに開ける
window.navigator.msSaveOrOpenBlob(blob, "test.txt");
} else {
document.getElementById("download").href = window.URL.createObjectURL(blob);
}
}
</script>
<a id="download" href="#" download="test.txt" onclick="handleDownload()">ダウンロード</a>
</body>
</html>
おまけ: 日本語を含むCSVファイルのダウンロード
ファイルダウンロード処理でよくありがちなCSVファイルのダウンロードを本方式で行うと、UTF-8のためそのままではExcelでは開けないという問題があります。実はExcelはBOM付きにするとUTF-8で開くことができますので、BOMを付与してダウンロードさせればOK。以下、CSVファイルダウンロードのサンプルコードです。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Download Sample</title>
</head>
<body>
<script type='text/javascript'>
function handleDownload() {
var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
var content = 'あいうえお,かきくけこ,さしすせそ';
var blob = new Blob([ bom, content ], { "type" : "text/csv" });
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blob, "test.csv");
// msSaveOrOpenBlobの場合はファイルを保存せずに開ける
window.navigator.msSaveOrOpenBlob(blob, "test.csv");
} else {
document.getElementById("download").href = window.URL.createObjectURL(blob);
}
}
</script>
<a id="download" href="#" download="test.csv" onclick="handleDownload()">ダウンロード</a>
</body>
</html>
これでExcel好きな人にも大丈夫ですね!!