【PHP】ファイルをダウンロードさせる方法!header関数でユーザーにファイルを提供しよう!
この記事からわかること
- phpでファイルをユーザーにダウンロードさせる方法
- header関数の「Content-Type」ヘッダとは?
- CSSファイルをダウンロードさせる時の注意点
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
自分で作成したCSSファイルなどをユーザー側に送信したい時に、webページからダウンロードできるようにしてあるととても便利ですよね!
今回はダウンロードボタンの作り方と注意点を解説していきます!
phpでユーザーにファイルをダウンロードさせる方法
ダウンロードさせたいファイルによってコードも少し変わってきます。
CSSファイルのダウンロード方法
header('Content-Type: text/css');
header('Content-Disposition:attachment;filename = "style.css"');
header('Content-Length: '.filesize("style.css"));
echo file_get_contents('style.css');
exit;
zipファイルのダウンロード方法
header("Content-type: application/zip");
header('Content-Disposition:attachment;filename = "file.zip"');
header('Content-Length: '.filesize("file.zip"));
echo file_get_contents('file.zip');
exit;
pngファイルのダウンロード方法
header('Content-Type: image/png');
header('Content-Disposition:attachment;filename = "guitar.png"');
header('Content-Length: '.filesize('guitar.png'));
echo file_get_contents('guitar.png');
exit;
ファイルをダウンロードさせるにはこのようにheader関数を使うとダウンロードさせることができます。
コードを実行するとブラウザにもよりますが、下部にダウンロードバーが表示されユーザーのデバイスのダウンロードフォルダの中にファイルがダウンロードされます。
ダウンロードさせるコード解説
header('Content-Type: コンテンツタイプ ');
// ファイルのコンテンツタイプを指定
header('Content-Disposition:attachment;filename = " 任意のファイル名 "');
// ファイルのダウンロードバーを表示; ダウンロード後のファイル名を設定
header('Content-Length: '.filesize(' ファイルのパス '));
// ファイルの大きさを明示
echo file_get_contents(' ファイルのパス ');
// ファイルを出力
exit;
// 処理を終了
ファイルのダウンロードは基本的にこの流れで行います。最初にダウンロードさせるファイルの種類を設定し、その後にダウンロードバーを表示させます。
その後にファイルのサイズをfilesize関数
で取得し、file_get_contents関数
で実際にファイルを出力しています。両者の関数とも引数にはファイルのパスを指定することに注意してください。
ダウンロードするのはこのコードが書いてあるページに出力されている内容なので最後にexit関数
でそのページの処理を強制終了させます。それによりページの上部からexit関数の間に出力されているデータのみがダウンロードされます。
なのでexit関数
をつけ忘れるとその下に記述しているコードも全てダウンロードされてしまうなんてこともあります。
ただしexit関数をつけ忘れてもファイルサイズを明示的に指定していれば防ぐことができます。
余分なデータをダウンロードさせないようにする
例えば以下の場合だと「内緒のコード」部分もcssファイルに組み込まれてダウンロードされてしまいます。
ファイルサイズを指定しない
header('Content-Type: text/css');
header('Content-Disposition:attachment;filename = "style.css"');
echo "内緒のコード";
echo file_get_contents('style.css');
exit;
// この場合は以下は大丈夫
echo "もっと内緒のコード";
ファイルサイズを指定しない&exitも付け忘れる
header('Content-Type: text/css');
header('Content-Disposition:attachment;filename = "style.css"');
echo file_get_contents('style.css');
echo "内緒のコード";
echo "もっと内緒のコード";
// 全ての出力データをダウンロードされてしまう
ファイルサイズを指定しておけば余分なデータをダウンロードさせないですみます。
コンテンツタイプがテキストの場合だとこのような挙動が起きますが、PNGやzipの場合だとダウンロードさせたファイル自体が壊れてしまったり開かない自体が発生するので注意しましょう!
余分なデータをダウンロードさせない方法
- コンテンツタイプを適切なものを指定する
- filesize関数で取得したファイルサイズを指定する
- ダウンロード処理後はexit関数で強制終了させる
コンテンツタイプの種類
指定できるコンテンツタイプには色々な種類が用意されています。
header('Content-Type: コンテンツタイプ ');
コンテンツタイプ | ファイル |
---|---|
text/html | HTML文書 |
text/css | CSSファイル |
image/jpeg | jpeg画像 |
image/png | png画像 |
application/zip | zipファイル |
application/octet-stream | バイナリファイル※ |
phpでは何も指定しないと「text/html」を出力します。それ以外のファイルをダウンロードさせたい時には明示的にコンテンツタイプを変更してあげましょう。
※バイナリファイルとはテキストファイル以外のファイルのことです。画像ファイルや動画ファイルなど文字形式でないファイルのことを指します。なのでjpegやpngなどはapplication/octet-stream
でも正しいということになります。
使い回しできるダウンロードコード
$file = "../css/style.css"; // ココのパスを変更するだけ
header('Content-Type: text/css');
header('Content-Disposition:attachment;filename = "'.basename($file).'"');
header('Content-Length: ' . filesize($file));
echo file_get_contents($file);
exit;
変数$file
にダウンロードさせたいファイルのパスを指定します。
あとはbasename関数
を使ってファイル名を取得、パスはそのまま変数を充てがうだけでOKです!
関連記事:【PHP】ファイル名や絶対パスの取得方法!パスは汎用性の高いコードを記述しよう
ダウンロードボタンの設置
<?php if(isset($_POST['download'] ) && $_POST['download'] === "ファイルをダウンロード"){ $file = "../css/style.css"; // ココのパスを変更するだけ header('Content-Type: text/css'); header('Content-Disposition:attachment;filename = "'.basename($file).'"'); header('Content-Length: ' . filesize($file)); echo file_get_contents($file); exit; } ?>
// HTMLコード <form action="php-download.php" method="POST"> <input class="dwn-btn" type="submit" name="download" value="ファイルをダウンロード"> </form>
下に実際のダウンロードボタンを設置してみました。ダウンロードできるのはこのボタンのCSSです。(現在調整中)
このようにform要素を使うことでボタンをクリックしたらファイルをダウンロードさせることができます。
ダウンロードコードの注意点
ダウンロードコードはphpファイルの1番上に持ってくる
上のコードでいうところの1〜10行目の部分です。その部分より上に別のコード(HTML)があるとその部分も含まれてしまいます。ダウンロードされるのはこのページに出力されているデータでした。
なのでダウンロードコードの前に出力があるとそれも含まれてしまうので1番上に持ってくるのが安心できると思います。
別コードの注意点
短い内容のものであればファイルでなくてもダウンロードさせることが可能です。
例えばCSSを少しだけダウンロードさせたい場合このようなコードを書くこともできます。
ファイルを作らないでCSSファイルをダウンロード
header('Content-Type: text/css'); header('Content-Disposition:attachment;filename = "style.css"'); $css = <<<END
@charset "utf-8"; .dwn-btn{ display: block; width: 200px; margin: 20px auto; padding: 15px; color:#fff; font-size: 1.4rem; background-color: darkcyan; border: none; cursor: pointer; }
END; echo $css; exit;
データを出力すれば良いのですからecho
などで力技で出力した文字もファイルに変換してダウンロードさせることができます。その際はヒアドキュメント(<<<END〜END
)を使えば改行やタブを気にせず出力することができます。
readfile関数でのダウンロード方法
$file = "../css/style.css";
header('Content-Type: text/css');
header('Content-Disposition:attachment;filename = "'.basename($file).'"');
// header('Content-Length: ' . filesize($file)); // 忘れてしまうと
echo readfile($file);
exit;
// 出力されるのはファイルの内容+ファイルのバイト数
出力する関数であれば基本的に問題なく動作させることが可能です。しかし例えばreadfile関数
であれば指定したファイルを読み込み、ファイルのバイト数を返り値として返します。Content-Length
でしっかりファイルサイズを指定していれば良いですが指定し忘れるとテキストファイルの最後にバイト数が記載されてしまったりするので注意が必要です。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。