SQLの窓

2019年01月24日


PHP の cURL でファイルアップロード

cURL を使うとWEBの通信部分の面倒な部分( ssl や ファイルアップロード ) を簡単に処理してくれます。ここで、file-upload.php は、WEB サーバー上ですが、upload.php は、Windows のローカルPC から、コマンドプロンプトで php.exe upload.php で実行可能です

※ 昔と違って、CURLFile クラス を使わないとファイルをアップロードできません

※ MIME 情報は Fileinfo 関数 で取得しています。

関連する記事

VBScript から PHP へファイルアップロード
PHP : cURL で FTP + SSL ダウンロード

file-upload.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ファイルアップロードの簡易テンプレート</title>
</head>
<body>
<form 
	enctype="multipart/form-data"
	method="POST">
 
	アップロードするファイル : 
	<input name="target" type="file">
	<p><input type="submit" value="アップロード"></p>
 
</form>
<pre>
<?php
if ( $_SERVER['REQUEST_METHOD'] == "POST" ) {

	// アップロードするフォルダ
	$upload = realpath ( "./image" );
	// アップロードするファイル
	$upload .= ( "\\" . str_replace( "%", "", urlencode( $_FILES['target']['name'] ) ));
	// 一時ファイルをアップロードファイルとして移動
	if ( move_uploaded_file(
		$_FILES['target']['tmp_name'], $upload ) ) {
		print "アップロードに成功しました<br>\n";
	}

	// アップロード情報の表示
	print_r( $_FILES );

}

?>
</pre>
</body>
</html>


upload.php
<?php
// ***************************************************
// curl 処理
// ***************************************************
$url = "http://localhost/lightbox/20190124/file-upload.php";

$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $url);

// POST ( デフォルトは GET )
curl_setopt($curl, CURLOPT_POST, true);

// アップロードするファイル
$path = 'lightbox.jpg';

// Windows では extension=php_fileinfo.dll が必要
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
finfo_close($finfo);

// CURLFile クラスのコンストラクタ
// 1) 実際のファイルのパス
// 2) ファイルの MIME
// 3) アップロード先に渡すファイル名
$data = array( 'target' => new CURLFile($path, $mime, 'lightbox-upload.jpg') );
curl_setopt($curl, CURLOPT_POSTFIELDS, $data );

// ***************************************************
// デバッグ用
// ***************************************************
curl_setopt($curl, CURLOPT_VERBOSE, true);	

$handle1 = fopen("./debug.txt", "w");
curl_setopt($curl, CURLOPT_STDERR, $handle1);

$handle2 = fopen("./ret_header.txt", "w");
curl_setopt($curl, CURLOPT_WRITEHEADER, $handle2);

// ***************************************************
// SSL
// ***************************************************
if ( substr( $url, 0, 5 ) == "https" ) {
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
}

// ***************************************************
// 送信
// ***************************************************
$result = curl_exec($curl);

// ***************************************************
// 結果
// ***************************************************
if($result === false) {
	$result = 'Curl error: ' . curl_error($curl);
}
curl_close($curl);
fclose($handle2);
fclose($handle1);

print( $result . "\n" );

?>





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

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





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 + 通信 | このブログの読者になる | 更新情報をチェックする

2018年10月18日


PHP の imap 関数で( Windows ローカル )、Yahoo メールのメールをさくらインターネットのメールへコピーする

imap_append でデータを追加しているので、同じメールでも追加されて増えていきます。

メッセージ作成に時間がかかるので、WEB 上の実行の場合は、タイムアウトに注意する必要があります。

imap_utf8_to_mutf7 は、日本語で作成されたフォルダに対して必要です。
<?php
error_reporting( E_ALL & ~E_NOTICE & ~E_STRICT );
session_cache_limiter('nocache');
session_start();

header( "Access-Control-Allow-Origin: *" );
header( "Content-Type: application/json; charset=utf-8" );

# デバッグログの初期化
file_put_contents("debug.log", "開始\n" );

mb_internal_encoding("UTF-8");

xlog("ログの出力");

# ***************************
# IMAP 接続( 送信元 )
# ***************************
$con = @imap_open("{imap.mail.yahoo.co.jp:993/imap/ssl}INBOX", "アカウント", "パスワード");
if ( $con === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

# ***************************
# IMAP 接続( 送信先 )
# ***************************
$folder = imap_utf8_to_mutf7("個人用");
$con2 = @imap_open("{さくらユーザ.sakura.ne.jp:993/imap/ssl}INBOX.{$folder}", "ユーザ@さくらユーザ.sakura.ne.jp", "パスワード");
if ( $con2 === FALSE ) {
	print imap_last_error();
	xlog(imap_last_error());
	exit();
}

# ***************************
// 現在のメールボックスに関する情報を得る
# ***************************
$mbox_info = imap_mailboxmsginfo( $con );
xlog("\n■■■ \$mbox_info 現在のメールボックスに関する情報 -------");
xlog( print_r( $mbox_info ,true ));

if( $mbox_info->Nmsgs == 0 ) {
	xlog( "メールメッセージがありません" );
	exit();
}

// ***************************
// メッセージ件数
// ***************************
$max = $mbox_info->Nmsgs;
xlog("【メッセージ件数:{$max}】" );

// 一番古いものから 30件
if ( $max > 30 ) {
	$max = 30;
}

// ***************************
// $max 〜 1
// 最新から表示
// ***************************
for( $i = 1; $i <= $max; $i++ ) {

	$header = imap_fetchheader( $con, $i );
	$body = imap_body( $con, $i );
	imap_append( $con2, "{さくらユーザ.sakura.ne.jp:993/imap/ssl}INBOX.{$folder}", $header . "\r\n" . $body );

}

// ***************************
// IMAP 接続解除
// ***************************
imap_close($con2);
imap_close($con);

print json_encode($mbox_info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

// ***************************
// ログ出力
// ***************************
function xlog($message) {
	file_put_contents("debug.log", "{$message}\n" , FILE_APPEND );
}
?>





posted by lightbox at 2018-10-18 15:22 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



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

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