PHP
JavaScript

aタグから、アクセス権限外のファイルをダウンロードする [php, js]

どんな状況のはなし?

例えば、サーバーが以下のような構成で、public_html配下が公開されているとする。

- server
    - public_html
        - html
            - document.html
        - js
            - document.js  
        - document.php
    - upload_data 
        - hoge.txt

ユーザーがブラウザからアクセスできるのは、public_html配下のみ。
すなわち、JavaScriptではpublic_html配下しかアクセスできない

したがって、upload_data配下のhoge.txtにアクセスしたければ、サーバー側のphpファイルを介す必要がある
本記事は、その方法をまとめよう!というもの

ちなみに、upload_dataディレクトリのように、非publicのディレクトリにファイルを置く手法は、ユーザーに直接アクセスさせたくない時に用いられる

具体的に何するの?

  1. aタグで、phpファイル読込
  2. phpで、サーバーからファイルをダウンロード
  3. ブラウザがよしなにしてくれる

☆ユーザーの現在地: 「/public_html/document.html 」として話を進める

実装!

準備 〜ディレクトリ構成〜

先述のように、ブラウザのjsがアクセスできるのはpublic_html配下のみ。
なので、ダウンロードを行うphpファイルをpublic_html配下に作成しておく。

こんなかんじになる
documentディレクトリを作成し、その下にdownload.phpを作成した

- server
    - public_html
        - html
            - document.html  // ユーザーの現在地
        - js
            - document.js
        - document.php
        - document
            - download.php
    - upload_data 
        - hoge.txt

html

document.html
<a href="../document/download.php"> hogeテキストファイルをダウンロード </a> 

php

download.php
<? php

//ダウンロードさせたいファイルのパス
$file_path = "/server/upload_data/hoge.txt";

//ダウンロード時のファイル名
$file_name = "hoge_test.txt";

//ファイルタイプの指定
header('Content-Type: application/force-download');
// ファイルサイズの取得
header('Content-Length: ' . filesize($file_path)); 
// ファイルのダウンロード及びリネームを指定
header('Content-disposition: attachment; filename="' . $file_name . '"');

//ファイルの読み込み(出力)
readfile($file_path);

?>

完成

aタグをクリックすると、ブラウザ上にダウンロードダイアログが出てくる!

うっかりミスに注意

readfile()の前後に、Logger::info()echo()があると、それもファイルに書き込まれてしまう
ちなみに、その文字はたいてい文字化けしてる

参考

PHP 公式ドキュメント readfile
PHP 公式ドキュメント header
PHPでファイルをダウンロードする方法