3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(PHP)ページ遷移ありで違うサーバからファイルをダウンロードさせる方法

(PHP)PHPでファイルをダンロード(アクセス制限付き)とかぶってる内容ありです。

現在下記のような感じでダウンロードページを構築していました。

ダウンロードボタン押下→サンクスページに遷移→ファイル保存ダイアログが開く。

ちょうど、ベクターのダウロードのような感じです。

これで、現在はファイルをPHPスクリプトを置いてるレンタルサーバ上(ServerA)においてるんですが、このレンタルサーバがファイル転送の速度が遅いので、ダウンロードさせるファイルだけ、もっと高速な別レンタルサーバ(ServerB)に置いて欲しいという要件でした。

(ダウンロード一覧処理やページ遷移後のダウンロードなどは全て CakePHP でDBと連携させてますが、これらは元のレンタルサーバに置いたままとします。)

で、考えたのは、ServerBにダウンロードロジックを置いた PHP スクリプトを置いて、ServerA からリダイレクトでその PHP をたたくという方法です。

以下サンプルソースです。(ServerA側は CakePHP 使ってますが、普通のPHPに書き直しても使えると思います。)

ServerA側の CakePHP ダウンロード用コントローラ

class DownloadsController extends AppController{

var $name = "Downloads";

/**

* ダウンロードファイルリストの一覧作成・表示

*

* @access public

*/

function index(){

//省略。。。ここで、DBからダウンロードさせるファイルの一覧を取得してます。*/

}

 

/*

* ダウンロードメッセージ表示ページ

* ダウンロード案内のメッセージを表示し、ダウンロードを行うページへの遷移を行う。

*

* @param int $id ダウンロードする対象のid (downloads.id)

* @access public

*/

function get( $id ){

//レイアウトファイルはdown.ctpを使う。

$this->layout = 'down';

//DBから指定されたidのデータ取得

$where = array("id" => $id );

$dwn = $this->Download->find( $where );

 

//存在しないもしくはダウンロード許可されていない場合はエラーメッセージ

if ($dwn == null)

{

$msg = '存在しないファイルが指定されました。ダウンロードできません。';

}else{

$msg = '

※ダウンロードに関する注意点

お使いのブラウザや設定によっては「セキュリティ保護のため...」という情報バーが表示される場合があります。


もしくは$dwn['Download']['name'] . '">こちらのリンクからダウンロードしてください。
';

//ダウンロードページ遷移のヘッダを埋め込む($dwn['Download']['name']にはダウンロードさせるファイル名が格納)

$metaRefresh = '$dwn['Download']['name'] .'">';

//ダウンページ遷移ヘッダをレイアウトにセット(レイアウトファイルのヘッダにこのメタデータを出力する記述がいる)

$this->set('metaRefresh', $metaRefresh);

}

$this->set('msg', $msg);

}

 

/*

* ダウンロード処理

* 引数で渡されたidのダウンロードファイルを実際にダイアログを表示させてダウンロードさせる。

*

* @param int $filename ダウンロードする対象のファイル名

* @access public

*/

function down( $filename )

{

if ($filename != null)

{

//ServerBのダウンロード処理PHPにリダイレクト

header("Location:http://ServerB/down.php?file=" . $filename);

exit;

}

}

 

}

?>

ServerA側の CakePHP ダウンロード用レイアウトファイル(ダウンロードページ遷移へのメタデータ)

xmlns="http://www.w3.org/1999/xhtml">

 

</span></a></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">

<?php //ダウンロード用メタデータメタデータがあれば、それを出力。メタ情報用変数がなければ何もしない ?>

<?php if ( isset( $metaRefresh ) ) : ?>

<?php echo $metaRefresh ?>

<?php endif; ?>

省略....

 

省略....

ServerB側で実際にダウンロード処理を行うPHP(GET変数でファイル名をもらう)

//ダウンロード開始させる

 

//GET引数取得(downloadファイル名が入る)

$path_file = $_GET["file"];

/* ファイルの存在確認 */

if (!file_exists($path_file)) {

die("Error: File(".$path_file.") does not exist");

}

 

/* オープンできるか確認 */

if (!($fp = fopen($path_file, "r"))) {

die("Error: Cannot open the file(".$path_file.")");

}

fclose($fp);

 

/* ファイルサイズの確認 */

if (($content_length = filesize($path_file)) == 0) {

die("Error: File size is 0.(".$path_file.")");

}

 

/* ダウンロード用のHTTPヘッダ送信 */

header("Content-Disposition: inline; filename=\"".basename($path_file)."\"");

header("Content-Length: ".$content_length);

header("Content-Type: application/octet-stream");

 

/* ファイルを読んで出力 */

if (!readfile($path_file)) {

die("Cannot read the file(".$path_file.")");

}

 

?>