PDFファイルなどをブラウザで表示させずに強制的にダウンロード保存させる方法

通常、ウェブブラウザからPDF・MP3・MP4などのリンクをクリックするとブラウザ上で表示(再生)されますが、サイトによっては、表示させずにパソコン上にダウンロード保存させたい場合があると思います。

リンクを右クリックして保存する事もできますが、みんなが知っているわけではありません。注意書きをして保存を促すという手段もありますがユーザーは手間に思うかもしれません。そこで、強制的にダウンロード保存させるいくつかの方法をご紹介します。

ダウンロード(表示と保存)について

そもそも、そのまま表示されるファイルと保存されるファイルはどのようにして決められているのでしょうか。まずはダウンロードについて簡単に説明をします。

ウェブブラウザ上でリンクをクリック(もしくはURLを直接入力)するとダウンロードが始まります。ダウンロードの動作には2種類あって、ブラウザで表示(再生)されるパターンと、パソコンに保存されるパターンがあります。

例外もありますが、このような動作は、ファイルの「拡張子」と「MIMEタイプ」によって決められています。

「拡張子」については説明するまでもありませんが、「.pdf」「.html」にあたる部分です。

「MIMEタイプ」は、ウェブサーバー上で拡張子と紐つけされている「ファイルの種類を表すもの」というように思っていただければさしずめ問題ないと思います。

ブラウザからリンクをクリックすると拡張子の情報がウェブサーバーに送られ、ウェブサーバーはその拡張子を元にMIMEタイプを返します。ブラウザはそのMIMEタイプを見て、「.pdf」や「.mp3」ならそのまま表示、「.zip」や「.lzh」なら保存というように動作します。

ファイルを圧縮してダウンロード保存させる

昔から定番の方法で、「.zip」や「.lzh」に圧縮すると、パソコン上にダウンロード保存できるようになります。ただ、ファイルの数が多いと手間だったり、端末によっては圧縮・解凍するために専用のアプリをダウンロードする必要がある場合もあります。

また、OSが違う場合やアプリの種類によってはうまく解凍ができないといったことが起こる場合もあるので、圧縮ファイルを作る際は注意が必要です。

.htaccessでMIMEタイプを変更してダウンロード保存させる

Apacheのウェブサーバーであれば、「.htaccess」に記述する事で、MIMEタイプを変更(偽装)する事ができます。

JPEGのMIMEタイプは「image/jpeg」など、PDFのMIMEタイプは「application/pdf」や「application/x-pdf」などです。これらのMIMEタイプはブラウザで「表示するファイル」として認識されますので、「保存するファイル」として認識されるMIMEタイプに変更します。

「octet-stream」は「.exe」などのMIMEタイプなので、「保存するファイル」として判断されるようになります。変更したい拡張子が複数ある場合は半角スペースで区切ります。

.htaccess
AddType application/octet-stream .pdf .mp3 .mp4

その他にも「.zip」や「.lzh」などの圧縮ファイルのMIMEタイプに変更しても同じく「保存するファイル」として判断されます。

.htaccess
AddType application/x-compress .pdf .mp3 .mp4

いいか悪いかはわかりませんが、存在しない架空のMIMEタイプを指定した場合でも同様の動作になります。ネット上では「force-download」という架空のMIMEタイプをよく見かけますが、語呂がいいから使用しているだけで「hogehoge」でも「unko」でもかまいません。

.htaccess
AddType application/hogehoge .pdf .mp3 .mp4

.htaccessの場合、設置したディレクトリ以下のファイルに一括で適用できるというメリットがありますが、個別のファイルだけに適用したいといった場合には向いていません。

PHPでファイルをダウンロード保存させる

PHPでHTTPヘッダー「Content-Disposition」を使ってダウンロード保存させることもできます。「attachment」ならダウンロードのダイアログが表示されて保存できるようになり、「inline」ならばそのまま表示されます。HTTPヘッダーを利用しますので、ここではMIMEタイプを偽装する必要はありません。

「filename=""」には任意のファイル名を指定する事ができます。

PHP
//ディレクトリのパス
$dir_path = "images/";

//ファイルタイプ(MIMEタイプ)を指定
header('Content-Type: application/pdf');

//ダウンロードタイプと保存時のファイル名
header('Content-Disposition: attachment; ilename="sample.jpg"');

//ファイルサイズを取得
header('Content-Length: '.filesize($dir_path . 'sample.pdf'));

//ファイルの読み込み
readfile($dir_path . "sample.pdf");

上記のコードを「dl.php」という名前で保存した場合、以下のように使用します。

HTML
<a href="./dl.php">ダウンロード</a>

このスクリプトですと、ダウンロード保存させたいファイルが複数ある場合は同じ数のPHPファイルを用意しないといけません。例えば「dl.php?id=file1」「dl.php?id=file2」というようにパラメータでダウンロード保存させたいファイルを切り替えられるよう改造すると一つのPHPファイルで済むのでスマートになると思います。

PHP
//ディレクトリのパス
$dir_path = "images/";

//キーとファイル名
$file = array(
	'file1' => 'sample1.pdf',
	'file2' => 'sample2.pdf',
	'file3' => 'sample3.pdf',
	'file4' => 'sample4.pdf',
	'file5' => 'sample5.pdf'
);

if(isset($_GET['id'])){
	foreach($file as $key => $value){
		if($_GET['id'] == $key){
			//ファイルタイプ(MIMEタイプ)を指定
			header('Content-Type: application/pdf');

			//ダウンロードタイプと保存時のファイル名
			header('Content-Disposition: attachment; filename="' . $value . '"');

			//ファイルサイズを取得
			header('Content-Length: '.filesize($dir_path . $value));

			//ファイルの読み込み
			readfile($dir_path . $value);

			break;
		}
	}
}

僕はプログラマーではないためコードの書き方には自信がありませんが、動作は確認しています。以下のようにリンクを指定します。

HTML
<a href="./dl.php?id=file1">ダウンロード1</a>
<a href="./dl.php?id=file2">ダウンロード2</a>
<a href="./dl.php?id=file3">ダウンロード3</a>
・
・

HTML5を使ってダウンロード保存させる

HTML5では上記のような面倒なことをせずにアンカータグに「download」属性 を追加するだけでダウンロード保存させることができるようになります。「download」の値には任意のファイル名を指定することができます。値が空欄の場合は元のファイル名で保存されます。

HTML
<a href="./images/sample.pdf" download="sample.pdf">

一番簡単で便利な方法ですが、古いブラウザには対応していない可能性があります。またモダンブラウザでも、Safari(v9.0.1現在)は対応していませんでした。

最終更新日:2017/08/23