SQLの窓

2018年02月17日


PHP : WEB でもコマンドラインでも HTTP でファイルをダウンロードする 『fget.php』

fopen wrappers が有効の場合、WEB 上で配置するとそのサーバー以外の別のサーバにあるファイルを http 経由でいったん読み込んでからクライアントへ送ります。その際、ファイルサイズが必要になるので、readfile に先立って、cURL で、ファイルサイズだけを取得しています。

readfile は、このような処理に使う為の関数ですが、標準出力へ内容を出力するので、コマンドプロンプトで使う場合は、ファイルへリダイレクトする必要があります。なので、ここでは通常のファイル処理としてファイルを書き込んでいます。

fget.php
<?php
// **************************************************
// 【fget.php】
// http:// で他のサーバのファイルを読み込んでダウンロードします
// 【利用方法】
// WEB : fget.php?target=URLエンコードされたURL
// CMD : php.exe fget.php URL
// **************************************************

// **************************************************
// コマンドラインでも使えるように
// **************************************************
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
	$remoteFile = $_GET['target'];
}
else {
	$remoteFile = $argv[1];
}
$fileName = basename($remoteFile);

// **************************************************
// PHP オンラインマニュアルの投稿データより
// **************************************************
$ch = curl_init($remoteFile);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if ( substr( $remoteFile, 0, 5 ) == "https" ) {
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
}
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
	echo 'cURL failed';
	exit;
}

$contentLength = 'unknown';
$status = 'unknown';
if (preg_match('/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches)) {
	$status = (int)$matches[1];
}
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
	$contentLength = (int)$matches[1];
}

// **************************************************
// WEB 経由ダウンロード
// **************************************************
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
	header( "Content-Type: application/octet-stream" );
	header( "Content-disposition: attachment; filename={$fileName}" );

	$path = $remoteFile;

	header( "Content-Length: $contentLength" );

	readfile($path);

	exit();
}
// **************************************************
// Windows コマンドライン
// Windows では、fopen()の mode パラメータに 'b' を
// 指定してファイルをオープンする必要があります。
// **************************************************
else {
	$ihandle = fopen($remoteFile, "rb");
	$ohandle = fopen($fileName, "wb");
	if ( $ihandle ) {

		while( !feof($ihandle) ) {
			$ret = fread( $ihandle, 1024 );
			fwrite( $ohandle,  $ret );
		}

		fclose( $ohandle );
		fclose( $ihandle );
	}

	exit();
}

?>


関連する情報

PHP fread

fread の第二引数は、読み込む最大バイトなので、EOF に達すると、それ以内のデータが取得されます。

PHP fwrite

大きなファイルですと、問題が出るという報告もあるので、その場合は以下のように readfile を書き換えるといいかもしれません。
Streaming a large file using PHP

Problem with download of larger files





【PHP + 通信の最新記事】
posted by lightbox at 2018-02-17 16:00 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり