これらのブラウザでファイルのダウンロードをさせようとすると、Safariでつまずく。IEですらできるのに、Safariだとできない。新しいタブにダウンロードするファイルの内容を表示して、ユーザにコピペさせるという最悪の動作しかできない。そのようにクライアントサイド(JavaScript)だけでファイルをダウンロードさせる方法を試しているうちにSafari沼にハマってしまった。
ということで、試した内容をまとめようと思う。
- aタグにdownload属性を追加する
- Content-Typeにapplication/octet-streamを指定する
- Content-Dispositionを指定する(サーバサイドの実装が必要)
検証環境は以下のとおり。
- macOS Yosemite
- Safari 10.0.2
aタグにdownload属性を追加する(失敗1)
まずは、HTML5で新たに追加されたdownload属性を追加する方法。
この属性を追加すると、リンクをクリックしたときにダウンロードするように促したりできる。
const blob = new Blob(['hoge'], { type: 'text/plain' });
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = 'dl1.txt';
a.target = '_blank';
a.click();
より具体的でかつクロスブラウザ対応したい場合は、以下の記事を参考にしてほしい。
実際に実行してみていただければわかるが、Safariではタブにファイルの内容を表示するだけに留まってしまう。(今回はa.target = '_blank'を指定しているので別タブで開かれる)
Content-Typeにapplication/octet-streamを指定する(失敗2)
次に、blobのContent-Typeにapplication/octet-streamを指定する方法。
このMIMEタイプを使うと、headerにContent-Disposition: attachementを指定したのと同様の動作になり、ブラウザに「名前を付けて保存」をさせようとする。
const blob = new Blob(['hoge'], { type: 'application/octet-stream' });
saveAs(blob, 'dl2.txt')
クロスブラウザ対応が面倒でFileSaver.jsを使っている(saveAs)。処理的には先ほど紹介したdocument.createElement('a') 〜 a.click() と同じような動きになる。
実際に実行してみると、なんと自動的にファイルがダンロードされたではありませんか!!
ただ、ちょっとした問題が…。
それは、「Failed to load resource: フレームの読み込みが中断しました。」というエラーがコンソールに出力されていること。
もうひとつが、ファイル名が「Unknown」としてダウンロードされてしまうこと。
いろいろ調べても解決方法が見つからず、泣く泣くこの実装は断念した。
Content-Dispositionを指定する(成功)
会社のSlackで質問してみたり、友人に質問してみたり、stackoverflowをみたり、、、行き着いたのは、サーバサイド開発だった。headerにContent-Dispositionを指定することで、ローカルに保存させるように動作する。
<?php
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename=' . $_GET['id']);
echo json_encode('いろいろ');
?>
location.href = example.com/download?id=1234
ようやくSafariでも強制ダウンロードさせることができた。
さいごに
クライアントサイドで実装できる2つは、具体的には以下のような動作になる。
巷では「IE○ね!」とよく聞くが、私は断然「Safari○ね!!」
IE6〜9の対応をしたことがないからかもしれないけど、最近のIEはわりとまともに動いてくれる。Edgeなんて最高じゃないか!
それにくらべSafariはひどい。ジョブズの息吹だかしらないが、Safariがなくなれば世界もちょっとは平和になるだろう。少なくとも私の仕事人生において無駄な時間を費やさなくてすむ。
そして世の中のすべてのブラウザがChromeに統一されますように。
参考サイト
- a 要素 - HTML | MDN
- MIME タイプ - HTTP | MDN
- Content-Disposition - HTTP | MDN
- PDFなどのファイルを強制的にダウンロードさせる3つ方法の比較 [無料ホームページ作成クラウドサービス まめわざ]
written by @bc_rikko
0 件のコメント :
コメントを投稿