[PHP][downloadLink] ファイルダウンロードツール

2015年6月9日

PHP プログラミング

サーバー上にあるデータを他の人に渡したい時に、WEB公開ディレクトリに置いてあるファイルを直接指定したURLを公開すると、サイト内のフォルダ構成が見えてあまりいいURLとは言えない。 もし、そのファイルが置いてあるフォルダのディレクトリ表示した際に、ファイル一覧が表示されるような事になれば、情報漏洩にも繋がる可能性があります。 また、web公開エリアにおいておらず、ユーザーのホームディレクトリに置かれているファイルも、いちいちwebディレクトリに設置しなおすのも面倒くさい。 シンボリックで対応する場合も、ファイル単体で対応できないので、とてもめんどくさくなる。 そこで、簡単にダウンロードさせることができるURLを出力して、ダウンロードの実行ができるツールを作ってみました。

概要

  1. ダウンロードする階層をエンコードして見た目で分かりにくくする。
  2. エンコードされたURLからファイルをダウンロードさせる。
  3. サーバー内のどの領域でもダウンロード対象にする。
  4. ファイルの種類は問わない

プログラム

index.php

ツールの入り口になるソース。このファイルで全ての処理をさばく。 <?php require_once "lib.php"; require_once "libUrl.php"; $lib = new LIB(); //file-download if($_REQUEST['mode']=='dl' && $_REQUEST['path']){ $lib->dl($lib->code2str($_REQUEST['path'])); } //Encode else if($_REQUEST['mode']=='encode'){ echo $lib->str2code($_REQUEST['path']); } //Decode else if($_REQUEST['mode']=='decode'){ echo $lib->code2str($_REQUEST['code']); } //path->query(only one) else if($_REQUEST['mode']=='convert'){ $convert = $lib->path2query($_REQUEST['path']); $libUrl = new libUrl(); echo $libUrl->getUrl()."?mode=dl&path=".$convert; } //path->query(multi) else if($_REQUEST['mode']=='converts'){ $libUrl = new libUrl(); $_REQUEST['path'] = str_replace("\r\n","\n",$_REQUEST['path']); $_REQUEST['path'] = str_replace("\n\r","\n",$_REQUEST['path']); $converts = explode("\n",$_REQUEST['path']); for($i=0;$i<count($converts);$i++){ $converts[$i] = trim($converts[$i]); $converts[$i] = str_replace("\n","",$converts[$i]); $converts[$i] = str_replace("\r","",$converts[$i]); if(!$converts[$i]){continue;} $convert = $lib->path2query($converts[$i]); $html.= $libUrl->getUrl()."?mode=dl&path=".$convert."<br>"; } echo $html; } // download else{ //$lib->dl($lib->code2str($_REQUEST['p'])); echo file_get_contents("convert.html"); } exit();

lib.php

ダウンロードやURLエンコードなどの処理のライブラリ。 <?php class LIB{ //DownLoad function dl($path){ //ファイルが存在しない場合 if(!file_exists($path)){ if($_REQUEST['debug']){ echo $path; } else{ echo "not-dir:".$path; } return; } //ファイル名を取得 $file=basename($path); //DL用ヘッダ header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename='.$file); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($path)); readfile($path); } // [Encode] String -> Code function str2code($str){ unset($data); for($i=0;$i<strlen($str);$i++){ $data[] = sprintf("%03d",ord(substr($str,$i,1))); } return join("",$data); } // [Decode] Code -> String function code2str($code){ //3の倍数チェック if(strlen($code)%3){echo "no-match-code";return;} unset($strs); for($i=0;$i<strlen($code)/3;$i++){ $strs[] = chr(substr($code,$i*3,3)); } return join("",$strs); } // Full-path function path2query($path){ $code = $this->str2code($path); return $code; } }

libUrl.php

PHPはjavascriptと違って、自分のURLを取得するのが関数一発では難しいので(旧バージョンでは)URL取得するライブラリを付けます。 <?php class libUrl{ //port + domain [http://hoge.com:8800/] //現在のポートの取得(80 , 443 , その他) function getSite(){ //通常のhttp処理 if($_SERVER['SERVER_PORT']==80){ $site = 'http://'.$_SERVER['SERVER_NAME']; } //httpsページ処理 else if($_SERVER['SERVER_PORT']==443){ $site = 'https://'.$_SERVER['SERVER_NAME']; } //その他ペート処理 else{ $site = 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT']; } return $site; } //現在ページのサービスroot階層のパスを返す function getDir(){ $uri = $this->getSite(); $req = explode('?',$_SERVER['REQUEST_URI']); return $uri.dirname($req[0]." ")."/"; } //現在のクエリ無しパスを返す function getUrl(){ $uri = $this->getSite(); $req = explode('?',$_SERVER['REQUEST_URI']); $uri.= $req[0]; return $uri; } //フルパスを返す function getUri(){ $uri = $this->getSite(); if($_SERVER['REQUEST_URI']){ $uri.= $_SERVER['REQUEST_URI']; } else{ $uri = $this->getUrl.(($_SERVER['QUERY_STRING'])?"?".$_SERVER['QUERY_STRING']:""); } return $uri; } //基本ドメインを返す function getDomain(){ return $_SERVER['SERVER_NAME']; } //リダイレクト処理 function setUrl($url){ if(!$url){return;} header("Location: ".$url); } }

convert.html

表示用HTMLファイル。URLをコンバートするソースを記述。※デザインは一切入れていないので、気になる人はCSSを足してください。 <!DOCTYPE html> <html> <head> <title>DownLoadLink</title> </head> <body> <form method="post" action="index.php"> <input type="hidden" name="mode" value="converts"> <div>ダウンロードするファイルをサーバー内のFullPathで入力してください。</div> <!--input type="text" name="path" value=""--> <div><textarea name="path"></textarea></div> <div><input type="submit" value="Convert"></div> </form> </body> </html>

使い方

1.ページにアクセス

2.サーバー内のフルパスを記入

※複数ある場合は、改行で書き込んでください。 ※入力欄が狭い場合は、カーソルで拡大できます。

3.convertボタンを押す

以下の文字列が表示されます。 http://192.168.33.10/labo/downloadLink/index.php?mode=dl&path=047104111109101047116101115116047097097097 http://192.168.33.10/labo/downloadLink/index.php?mode=dl&path=047104111109101047116101115116047098098098

4.ダウンロードテスト

上記で表示されたURLをひとつずつブラウザのアドレスに入力すると、階層が間違っていないければ、ダウンロードが開始されます。

注意

容量の大きいファイルを扱う時は、PHPでreadしているので、一度メモリに格納されてしまうので、非力なサーバーの場合は、ファイル上限値を指定する必要があります。 ※現段階では、無制限なので、サーバーダウンする可能性があります。

今後

ダウンロードする際にロギングして、ダウンロードされたログ管理をしたり、DL数など計測を行なってサービス化してもいいかもしれません。 また、ユーザー登録させて、ユーザー権限に応じたダウンロードを振り分けたり、サーバーのディレクトリの内部リストをエンコードURLで表示できたりしてもいいかもしれません。

このブログを検索

ごあいさつ

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