PHPでheader()
を使ったファイルのダウンロード方法をご紹介します。
ファイル形式と、ファイルサイズの取得、ファイルのリネームの3つを行い、ファイルを読み込むだけで簡単にダウンロード可能です。
よくあるファイルダウンロード時のエラーも紹介しています。
目次
ファイルをダウンロードする
基本的なダウンロード方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// ファイルのパス $filepath = 'bigimg.jpg'; // リネーム後のファイル名 $filename = 'ダウンロード.jpg'; // ファイルタイプを指定 header('Content-Type: application/force-download'); // ファイルサイズを取得し、ダウンロードの進捗を表示 header('Content-Length: '.filesize($filepath)); // ファイルのダウンロード、リネームを指示 header('Content-Disposition: attachment; filename="'.$filename.'"'); // ファイルを読み込みダウンロードを実行 readfile($filepath); |
上記コードを記述したファイルにアクセスすると、即ダウンロードが始まります。
※firefoxなど一部のブラウザでは確認ダイアログが出ます。
readfile()
の部分はファイルを読み込む関数であればいいのでfile_get_contents()
でもいいのですが、大容量のファイルはうまく処理できないためreadfile()
で読み込むと良いでしょう。
特定のファイル形式を指定してダウンロード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// ファイルのパス $filepath = 'note.pdf'; // リネーム後のファイル名 $filename = 'ダウンロード.pdf'; // ファイルタイプにPDFを指定 header('Content-Type: application/pdf'); // ファイルサイズを取得し、ダウンロードの進捗を表示 header('Content-Length: '.filesize($filepath)); // ファイルのダウンロード、リネームを指示 header('Content-Disposition: attachment; filename="'.$filename.'"'); // ファイルを読み込みダウンロードを実行 readfile($filepath); |
上記では、ファイル形式をPDFで指定しました。
ファイル形式を明確に指定すると、ダウンロードせずにブラウザに直接表示させるなど、ファイルの処理方法の選択肢が拡がります。
もっと簡単にダウンロード
一部ブラウザでは以下のような簡単なコードでもダウンロードできましたよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// ファイルのパス $filepath = 'bigimg.jpg'; // リネーム後のファイル名 $filename = 'ダウンロード.jpg'; // ファイルタイプを指定→ここを省略! // header('Content-Type: application/force-download'); // ファイルサイズを取得し、ダウンロードの進捗を表示→ここも省略! //header('Content-Length: '.filesize($filepath)); // ファイルのダウンロード、リネームを指示→attachmentを省略 // header('Content-Disposition: attachment; filename="'.$filename.'"'); header('Content-Disposition: filename="'.$filename.'"'); // ファイルを読み込みダウンロードを実行 readfile($filepath); |
application/force-download
Content-Length
Content-Disposition: attachment
を省略しました。
Content-Type:
PDFや画像などファイルタイプを指定します。
このapplication/force-download
を省略してもgoogle chromeとfirefoxでは問題なくダウンロードされました。
ただ、safariなど一部のブラウザではhtmlファイルとしてダウンロードされたため、省略することで違うファイルとして誤認識されてしまいました。
Content-Length:
ファイルサイズを取得し、ダウンロードの進捗を%表示してくれます。
Content-Length:
の後に、元ファイル名またはパス名を指定します。
無くてもダウンロードはされますが、ダウンロードの進捗が分からないのは不便ですね。
Content-Disposition: attachent
ファイルの処理方法を指定します。
省略するとデフォルト値であるinline
が指定されますが、これはファイルをダウンロードせずそのまま表示させる指示となります。
attachment
はダウンロードの指示です。
ただ、Content-Type: application...
で指定したファイルが明確でない場合は、ダウンロードされます。
最初の基本的な使い方のサンプルは、ファイル形式を敢えてブラウザに認識させずダウンロードさせたものです。
バグの元にもなるので、よほど理由がない限りは省略させずに記述した方がいいかと思います。
ダウンロードせずにブラウザにそのまま表示
おまけで、ダウンロードせずにブラウザに直接表示させる方法もご紹介します。
PDFファイルを表示させる
Content-Typeに application/pdf
を指定します。
1 2 3 4 5 6 7 8 |
// PDFファイルのパス $filepath = 'note.pdf'; // ファイルタイプにPDFを指定 header('Content-Type: application/pdf'); // ファイルを読み込む readfile($filepath); |
テキストファイルを表示させる
Content-Typeに text/plain
を指定します。
1 2 3 4 5 6 7 8 |
// テキストファイルのパス $filepath = 'note.txt'; // ファイルタイプにテキストを指定 header('Content-Type: text/plain'); // ファイルを読み込む readfile($filepath); |
よくあるエラー
全て.php型式でダウンロードされてしまう
.pdf
や.txt
などの形式でも、ダウンロードするとなぜか拡張子が全て.php
に変わってしまうことがあります。
それはContent-Disposition: filename
を省略したからでしょう。
1 2 |
// filenameを指定し、適切なファイル形式でダウンロードする header('Content-Disposition: filename="'.$filename.'"'); |
ダウンロード後のファイル名を決めるContent-Disposition: filename
は必ず指定するようにしましょう。
容量 0 の空ファイルがダウンロードされてしまう
ファイルを読み込む関数によっては、大容量のファイルを処理しきれないものがあります。
例えばfile_get_contents()
はファイルを読み込む際には便利ですが、容量が大きいダウンロードには向かないでしょう。
容量が0
のファイルがダウンロードされます。
1 2 3 4 5 |
// file_get_contentsは大容量ファイルを処理できない file_get_contents($filepath); // => NG! // readfileなら大容量でもOK! readfile($filepath); // => OK! |
容量の大きいファイルをダウンロードする際はreadfile()
を使いましょう。
header関数のエラー
サンプルのコードを記述してもなぜかエラーになるという人もいるでしょう。
以下のようなエラーが多いようです。
Warning: Cannot modify header information – headers already sent by (output started at…
これはすでにヘッダーが送信されていますよというエラーです。
ヘッダー関数の前にecho
やhtml
など何らかの出力すると上記のようなエラーが出ます。