【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関数で実際にファイルを出力しています。両者の関数とも引数にはファイルのパスを指定することに注意してください。

関連記事: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の場合だとダウンロードさせたファイル自体が壊れてしまったり開かない自体が発生するので注意しましょう!

余分なデータをダウンロードさせない方法

コンテンツタイプの種類

指定できるコンテンツタイプには色々な種類が用意されています。

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でしっかりファイルサイズを指定していれば良いですが指定し忘れるとテキストファイルの最後にバイト数が記載されてしまったりするので注意が必要です。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index