[PHP] WEBサイトのダウンロードの仕組み作り

2018年7月13日

PHP テクノロジー プログラミング

インターネットサービスでデータをダウンロードさせる処理に少し手こずったので、備忘録としてブログに記載。 そもそも、今回は、サービス内の特定データのみをzip圧縮してダウンロードさせる処理を行う時の仕組みです。 事前にzipファイルを作成して、URLで直リンクしてあげればいいと考える人は、少し浅はかですねえ。 URLでの直リンクは、セキュリティの観点から避けたいものです。

処理一覧

処理は以下のようなフローで行う事とします。
1. リンクをクリック 2. サーバー側でzip圧縮 3. ダウンロード処理 4. ダウンロード後にサーバーのzipファイルを削除
ダウンロードに関しては、データURLの痕跡を残さず、ダウンロード後は、データを削除するので、非常にセキュアな構造が作れます。

今回のプログラムの前提条件

データは複数のファイルが格納されているデータフォルダを圧縮する仕様です。 その際に使用するアーカイブタイプは、「zip」データを使用します。 これは、ダウンロードした後で、windowsでもmacでもデフォルトで使われているぐらい汎用性が高いので、zipを使うことにしてます。 最後に、このプログラムはPHPで実行されますが、Linux-OSで利用することを前提にしています。 もしzip圧縮プログラムがインストールされていない場合は、事前にインストールしておいてください。

ソースコード

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>fileDownload</title> </head> <body> <a href="download.php" target="_blank">ファイルをダウンロード</a> </body> </html> <?php makeZip(); function makeZip(){ $archivePath = "data/"; exec("zip -r download.zip " . $archivePath); downloadFile("download.zip"); } function downloadFile($path){ header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="'.basename($path).'"'); header('Content-Length: ' . filesize($path)); echo file_get_contents($path); unlink($path); } 上記プログラムと同一階層に"data"フォルダを作成してその中に何かしらのデータを複数入れておきます。

解説

まず、Aリンクでdownload.phpにアクセスしますが、この時にダウンロードするデータに条件をつけたい場合は、GETクエリを付けて行えます。 target="blank"を指定して、ダウンロード後にページが切り替わらないところがポイントですね。 ちなみに、AJAXを使ってこの処理を行おうとすると、ポップアップブロックが出てしまうので、ブラウザセキュリティに注意してください。 アクセスを受けたPHP側では、まずzipアーカイブファイルを生成します。 この時の生成は、PHPコマンドではなく、execを使ってLINUXコマンドをたたきます。 個人的にこの方が高速に行えるような気がしているので、ほかのやり方でも問題ありません。 そして、アーカイブができたら、download関数にアーカイブしたパスを送ります。 download処理としては、header関数を使って、"apprication/zip"を指定して、file_get_contentsで作成したzipファイルをそのままechoすることで、実際にzipファイルをリンクした状態を作ります。 この時の小技ですが、 header('Content-Disposition: attachment; filename="'.basename($path).'"'); と記述することで、ファイル名をコントロールできます。 ※サンプルでは、作成したarchiveと同じファイル名になります。 最後に、echoの後、unlinkすることで、作成したアーカイブデータを削除して完了になります。 ほかのサイトでは、"echo file_get_contents()"の箇所を"header("Location: ".$path);"としているケースがありますが、最後にファイルを削除しないのであれば、Locationで構わないのですが、echoすることで、unsync状態が作れて、完了後にきちんとデータ削除してくれるようになります。 最後に、とりあえず、複数のブラウザで確認しておきます。
・Google Chrome (mac) : ○ ・Safari (mac) : ○ ・Firefox (mac) : ○
windows系は確認していません。もしうまく動作しないブラウザがありましたら、教えてください。 とりあえず、結構アナログな手段ですが、こうした方法でダウンロードをセキュアに実装することが可能なので、便利に使ってみましょう。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ