SQLの窓

2019年01月21日


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

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

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

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

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

// 保存ファイル名をパスから作成
$fileName = basename($remoteFile);

// 保存ファイル名を指定した場合
if (substr(php_sapi_name(), 0, 3) == 'cgi') {
	// WEBアプリで 保存ファイル名を指定
	if ( isset($_GET['name']) ) {
		$fileName = $_GET['name'];
	}
}
else {
	// コマンドプロンプトで 保存ファイル名を指定
	if ( isset($argv[2]) ) {
		$fileName = $argv[2];
	}
}

// **************************************************
// PHP オンラインマニュアルの投稿データより
// ファイルのサイズを取得する cURL の処理
// **************************************************
$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 2019-01-21 16:12 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

PHP : cURL : Google Photo API の albums.list メソッドを使用して アルバム一覧データを取得する

Google Photo API を使用するには、認証されたアクセストークンが必要です。なので、ここで使用しているアクセストークンは、別のコードで取得したものをセッションに保存して利用しています。

$_SESSION['access_token']

アクセストークンは 3600 秒しか使用できないので随時必要な時に新たに取得する必要があります。( refresh_token を取得して使用します。その場合最初の認証の URL に access_type=offline をセットして認証する必要があります / ※ 認証時にしか取得できませんでした )

$_SESSION['access_token'] は、PHP + cURL で Google Photo API の アクセストークンを取得する のコードに session_start(); を先頭に追加してセッションを使用可能にしてから、以下のコードを最後に使用して保存します。
$token = json_decode($result, true);

print "<pre>";
print_r($token);
print "</pre>";

$_SESSION['access_token'] = $token['access_token'];

// ************************************
// refresh_token は、認証の URL に 
// access_type=offline を使用して
// 認証した最初のみ取得できるようです
// ************************************
if ( !isset( $_SESSION['refresh_token'] ) ) {
	$_SESSION['refresh_token'] = $token['refresh_token'];
}


album-list.php
<?php
session_cache_limiter('nocache');
session_start();

?>
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
</head>
<body>
<?php

print "<pre>";
print_r($_SESSION);
print "</pre>";

$start = true;
$page_token = '';

// ************************************
// curl 処理
// ************************************
$curl = curl_init();

// ************************************
// デバッグ用の詳しいメッセージを出力
// ************************************
curl_setopt($curl, CURLOPT_VERBOSE, true);
$fp_debug = fopen("./debug.txt","w");
curl_setopt($curl, CURLOPT_STDERR, $fp_debug);

// ************************************
// HTTP ヘッダ
// ************************************
$header[] = "Authorization: Bearer {$_SESSION['access_token']}";
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);

// ************************************
// オプション
// ************************************
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

// ************************************
// https 用
// ************************************
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);

// ************************************
// ヘッダ内容
// ************************************
$handle = fopen("./header.txt", "w");
curl_setopt($curl, CURLOPT_WRITEHEADER, $handle);
 
// ************************************
// アルバムを全て取得
// access_albums( ) が true を返す間
// ループする
// ************************************
while( access_albums( ) ) { }

// ************************************
// 終了処理
// ************************************
curl_close($curl);
fclose($fp_debug);
fclose($handle);

// ************************************
// アルバムを全て取得する関数
// ************************************
function access_albums( ) {

	// 開始フラグ
	global $start;

	// 最大50件の読み込みでまだアルバムがある場合に
	// セットされるデータ
	global $page_token;

	// cURL ハンドル
	global $curl;

	// 初回
	if ( $start ) {
		$start = false;
		$url = "https://photoslibrary.googleapis.com/v1/albums?pageSize=50";
	}
	// 2回目以降
	else {
		$url = "https://photoslibrary.googleapis.com/v1/albums?pageSize=50&pageToken={$page_token}";
	}

	// URL を設定( v1/albums は GET メソッド )
	curl_setopt($curl, CURLOPT_URL, $url );
	// ************************************
	// 送信
	// ************************************
	$result = curl_exec($curl);
	if($result === false) {
		// cURL そのものがエラー
		return false;
	}
	else {
		// 正しいデータを取得したので連想配列に変換
		$json = json_decode( $result, true );

		// 出力
		print "<pre>";
		print_r( $json );
		print "</pre>";

		// この呼び出しで全ての場合は false を返して終了
		if ( !isset( $json['nextPageToken'] )) {
			return false;
		}
	}

	// 次の一覧を取得する為のデータ
	$page_token = $json['nextPageToken'];

	// 次を読む
	return true;

}

?>
</body>
</html>





posted by lightbox at 2019-01-21 15:05 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

2019年01月20日


PHP + cURL で Google Photo API の アクセストークンを取得する

Google API ConsoleWebアプリケーションの OAuth クライアント ID を取得して使用します。そこには、承認済みのリダイレクト URI を登録して API からの呼び出しでその URI を呼べるようにします。

そうすると、以下の URL で Google API の oauth によりアカウントで権限の承認を行った後準備しておいた リダイレクト URI  にジャンプします。

その時 code が手に入るので、それと認証情報の他のデータを使って cURL で アクセストークンを取得します( アクセストークンの生存期間は3600秒 )

クライアント ID : 
登録した承認済みのリダイレクトURI : 



https://accounts.google.com/o/oauth2/v2/auth?client_id=クライアントID&response_type=code&scope=https://www.googleapis.com/auth/photoslibrary&redirect_uri=登録した承認済みのリダイレクトURI

承認済みのリダイレクト URI に用意する PHP
<?php

// ************************************
// 表示用
// ************************************
print "<pre>";
print_r($_GET);

// ************************************
// API データ
// ************************************
$client_id = 'クライアント ID';
$client_secret = 'クライアント シークレット';
$redirect_uri = 'http://localhost/gapi/examples/idtoken.php';

// ************************************
// curl 処理
// ************************************
$curl = curl_init();

// ************************************
// デバッグ用の詳しいメッセージを出力
// ************************************
curl_setopt($curl, CURLOPT_VERBOSE, true);
$fp_debug = fopen("./debug.txt","w");
curl_setopt($curl, CURLOPT_STDERR, $fp_debug);

// ************************************
// POST 処理
// ************************************
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_URL, "https://www.googleapis.com/oauth2/v4/token");
// ************************************
// データ
// ************************************
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query([
	'code' => $_GET['code'],
	'client_id' => $client_id,
	'client_secret' => $client_secret,
	'redirect_uri' => $redirect_uri,
	'grant_type' => 'authorization_code'
]));

// ************************************
// オプション
// ************************************
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

// ************************************
// https 用
// ************************************
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);

// ************************************
// ヘッダ内容
// ************************************
$handle = fopen("./header.txt", "w");
curl_setopt($curl, CURLOPT_WRITEHEADER, $handle);
 
// ************************************
// 送信
// ************************************
$result = curl_exec($curl);
if($result === false) {
	$result = 'Curl error: ' . curl_error($ch);
} 

// ************************************
// 終了処理
// ************************************
curl_close($curl);
fclose($fp_debug);
fclose($handle);
 
// ************************************
// 結果
// ************************************
print $result;

// ************************************
// 表示用
// ************************************
print "</pre>";

?>


関連する記事

Windows 用 curl で、Googls Photo API を呼び出して画像の baseUrl を取得する




posted by lightbox at 2019-01-20 20:39 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

PHP : cURL で FTP + SSL ダウンロード

サンプルは、PHP のオンラインマニュアルの投稿部分にあります。この、「投稿部分」には昔から結構重要な情報が掲載されています。特に、SSL についてはマニュアル本文に無いパラメータがあり、libcurl.a の Cドキュメントからの参照が記述されています。(実際、本文のパラメータだけは SSL にはなりませんでした)

以下は、コマンドプロンプトからの実行を想定していますので、実行は以下のようになります。
php.exe ftp_ssl_download.php

また、Windows では、php.ini で extension=php_curl.dll が必要です。実際、SSL が使われたかどうかの確認は、debug.txt を参照して確認できます。

ftp_ssl_download.php

<?php
// ************************************
// ユーザとパスワード
// ************************************
$username = 'ユーザ';
$password = 'パスワード';

// ************************************
// 対象ファイル
// ログインディレクトリからの相対位置
// ************************************
$url = 'ドメイン/www/homepage/download/WinOfSql102.zip';

// ************************************
// URL
// ************************************
$ftp_server = "ftp://" . $username . ":" . $password . "@" . $url;

// ************************************
// 開始
// ************************************
$ch = curl_init();

// ************************************
// デバッグ用の詳しいメッセージを出力
// ************************************
curl_setopt($ch, CURLOPT_VERBOSE, true); 
$fpe = fopen("./debug.txt","w");
curl_setopt($ch, CURLOPT_STDERR, $fpe);

// ************************************
// 転送用のオプション
// ************************************
curl_setopt($ch, CURLOPT_URL, $ftp_server);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// ************************************
// SSL である事の明示
// ※ CURLFTPSSL_ALL と CURLFTPSSL_TRY があります
// ************************************
curl_setopt($ch, CURLOPT_FTP_SSL, CURLFTPSSL_ALL);

// ************************************
// ダウンロードされるファイル
// ************************************
$fp = fopen("./target.zip","w");
curl_setopt($ch, CURLOPT_FILE, $fp);

// ************************************
// 実行
// ************************************
$result = curl_exec($ch);
if($result === false) {
	$result = 'Curl error: ' . curl_error($ch);
}

// ************************************
// 終了
// ************************************
curl_close($ch);

// ************************************
// 後処理
// ************************************
fclose($fp);
fclose($fpe);

print $result . "\n";
?>
OK





タグ:PHP Curl 通信
posted by lightbox at 2019-01-20 00:01 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

2019年01月18日


Windows 用 curl で、Googls Photo API を呼び出して画像の baseUrl を取得する

現実的に言って、Googls Photo API はまだ使わないほうがいいですが、今後の為に Google の API を使う上で oauth の扱いのサンプルと考えてテストしています。

Google からの情報で順に文字列を作成する必要があり、とても煩雑になるので、このブログで実行可能な簡単な curl のコマンドライン作成プログラムを用意しました。


Windows 用の curl をダウンロードする

https://curl.haxx.se/download.html






この時点では、curl-7.63.0-win64-mingw.zip 解凍して bin\curl.exe を実行しています


Google API Console でプロジェクトを作成し、認証情報より クライアント ID と クライアント シークレット を取得します。
※ curl で実行するので、OAuth 2.0 クライアント ID はその他で作成します


この作業は、こちらを参照して下さい。既にプロジェクト等がある人は以降の手順で access_token を取得します。


アプリケーション 用のコード を取得する URL の作成

クライアント ID : 




accss_token を取得するコマンドラインの作成

コード : 
クライアント シークレット : 




accss_token でアクセスするコマンドライン1

※ アルバム一覧を取得します
※ ここで取得した access_token は1時間しか有効ではありません。

access_token : 



accss_token でアクセスするコマンドライン2

アルバム id : 



このコマンドラインで、指定したアルバムの中にある画像の情報を取得できます。

但しこれで取得した baseUrl は、一応アドレスバーに入力すると画像が表示されますが、異常に長い URL であるのと、Content-Type を返さないという問題があります。(Content-Type を返したい場合は最後に =w幅 を追加します)

※ なので、その他いろいろな状況も鑑みて、現状この URL で img 要素を作成して運用するにはとてもリスクがあります。




▼ 補足
OAuth 2.0 Flow: Installed apps / urn:ietf:wg:oauth:2.0:oob について




posted by lightbox at 2019-01-18 20:01 | WEBサービス | このブログの読者になる | 更新情報をチェックする

2019年01月17日


JavaScript でテーブル要素の td をクリックしてテキストを選択する / Range オブジェクト

Range オブジェクトを使用して td 内部を選択します。

$(function(){
	$("#copy-table-td-text td").each(function(){
		$(this).css({ "cursor" : "default" });
	});

	$("#copy-table-td-text td").on("click",function(){

		if( $(this).get(0).cellIndex > 0  ) {
			var range = document.createRange();
			range.selectNodeContents( $(this).get(0) );
	
			var selection = window.getSelection();
			selection.removeAllRanges();
			selection.addRange(range);
		}
	});
});

イベントと td でのカーソル形状の変更は jQuery でコードを作成しています。

$(this).get(0) で、jQuery より DOM オブジェクトを取得し、cellIndex プロパティを使用して『どの列をクリックしたか』を判定しています
▼ クリックするとテキストを選択します
ファイル名を指定して実行 コマンドプロンプト エクスプローラのアドレス
1 ms-settings:about start ms-settings:about ms-settings:about
2 ms-settings:windowsupdate start ms-settings:windowsupdate ms-settings:windowsupdate
3 shell:startup start shell:startup shell:startup
4 shell:sendto start shell:sendto sendto
5 control control control
6 shell:ControlPanelFolder start shell:ControlPanelFolder shell:ControlPanelFolder
7 mspaint mspaint mspaint
1 %TEMP% start %TEMP% %TEMP%

▲ それぞれ Windows10 で実行可能なコマンドですが、場所によって微妙に引き渡す文字列が違っています。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
#lboxtable * {
	font-family: メイリオ,'MS Pゴシック';
	font-size: 12px;
}
#lboxtable table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	background-color: #FFFFFF;
}
#lboxtable td {
	padding: 5px;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	/* white-space: nowrap; */
}
#lboxtable th {
	padding: 5px;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	background-color: silver;
	/* white-space: nowrap; */
}
#lboxtable .header {
	padding: 5px;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	background-color: silver;
	/* white-space: nowrap; */
}
</style>
<script>
$(function(){
	$("#copy-table-td-text td").each(function(){
		$(this).css({ "cursor" : "default" });
	});

	$("#copy-table-td-text td").on("click",function(){

		if( $(this).get(0).cellIndex > 0  ) {
			var range = document.createRange();
			range.selectNodeContents( $(this).get(0) );
	
			var selection = window.getSelection();
			selection.removeAllRanges();
			selection.addRange(range);
		}
	});
});
</script>
<div id="lboxtable">
<strong><span style="color:#3300cc;">▼ クリックするとテキストを選択します</span></strong>
<table id="copy-table-td-text">
<tr>
  <th></th>
  <th>ファイル名を指定して実行</th>
  <th>コマンドプロンプト</th>
  <th>エクスプローラのアドレス</th>
 </tr>
 <tr>
  <td>1</td>
  <td>ms-settings:about</td>
  <td>start ms-settings:about</td>
  <td>ms-settings:about</td>
 </tr>
 <tr>
  <td>2</td>
  <td>ms-settings:windowsupdate</td>
  <td>start ms-settings:windowsupdate</td>
  <td>ms-settings:windowsupdate</td>
 </tr>
 <tr>
  <td>3</td>
  <td>shell:startup</td>
  <td>start shell:startup</td>
  <td>shell:startup</td>
 </tr>
 <tr>
  <td>4</td>
  <td>shell:sendto</td>
  <td>start shell:sendto</td>
  <td>sendto</td>
 </tr>
 <tr>
  <td>5</td>
  <td>control</td>
  <td>control</td>
  <td>control</td>
 </tr>
 <tr>
  <td>6</td>
  <td>shell:ControlPanelFolder</td>
  <td>start shell:ControlPanelFolder</td>
  <td>shell:ControlPanelFolder</td>
 </tr>
 <tr>
  <td>7</td>
  <td>mspaint</td>
  <td>mspaint</td>
  <td>mspaint</td>
 </tr>
 <tr>
  <td>1</td>
  <td>%TEMP%</td>
  <td>start %TEMP%</td>
  <td>%TEMP%</td>
 </tr></tbody>
</table>
</div>




posted by lightbox at 2019-01-17 14:54 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする
container 終わり

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

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