SQLの窓

2017年09月02日


FormData を使用して $.ajax で送信すると、ファイルのアップロードとメール送信(ファイル添付)を一度に行えます

mb_send_mail による メール送信におけるファイル添付の普通のサンプルはこちら

呼び出し
	$( "#base" ).submit(function( event ) {

		event.preventDefault();

		$("#action").prop( "disabled", true );
		$("#action_copy").prop( "disabled", true );
		
		// 新規送信用オブジェクト
		var formData = new FormData();

		// 入力テキスト
		formData.append("fld_to", $("input[name='fld_to']").val() );
		formData.append("fld_subject", $("input[name='fld_subject']").val() );
		formData.append("fld_body", $("textarea[name='fld_body']").val() );
		// ファイルオブジェクト( type="file" )
		formData.append("fld_file", $("input[name='fld_file']").get(0).files[0]);

		$.ajax({
			url: "app-mail.php",
			type: "POST",
			data: formData,
			processData: false,  // jQuery がデータを処理しないよう指定
			contentType: false   // jQuery が contentType を設定しないよう指定
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );

			if ( data.status == 0 ) {

				toastr.info("メールが送信されました");

				$("input[name='fld_subject']").val( "" );
				$("textarea[name='fld_body']").val( "" );

			}

			if ( data.status == 1 ) {
				// エラーメッセージを表示
				toastr.error("メール送信に失敗しました");

			}
			
		})
		// 失敗
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
		})
		// 常に実行
		.always(function() {

			$("#action").prop( "disabled", false );
			$("#action_copy").prop( "disabled", false );

		})
		;		
	
	});

受け側の PHP

$_POST['fld_body'] の中身は UTF-8 ですが、mb_send_mail が変換してくれます。
<?php
// ***************************
// このアプリ特有の定義
// ***************************
require_once("../mail-jquery/app.model");

$GLOBALS["content_type"] = "application/json";
$GLOBALS["upload_dir"] = "./upload";

require_once("{$GLOBALS["common_path"]}common.php");

// type="file" のフィールドの name の値
$fld = "fld_file";

// ******************************************************
// アップロード 処理
// ******************************************************
if ( !$_FILES ) {
	// php.ini の upload_max_filesize を超えて、
	// Apache に制限が無いと $_FILE が空になる
	$_FILES[$fld]['error'] = 5;	// ユーザエラーメッセージ
}

// *************************************
// アップロード処理
// フィールド名 : $fld で固定
// *************************************

// true では実行しない
if ( !$GLOBALS["debug_update"] ) {

	$upload = realpath ( $GLOBALS["upload_dir"] );
	$upload .= ( DIRECTORY_SEPARATOR . $_FILES[$fld]['name'] );
	if ( move_uploaded_file(
		$_FILES[$fld]['tmp_name'], $upload ) ) {
		$_POST['result']  = "アップロードに成功しました";
	}
	else {
		if ( !$_FILES ) {
			$_FILES[$fld]['error'] = 5;	// ユーザエラーメッセージ
		}
		$_POST['result']  = "アップロードに失敗しました";
	}

}
else {
	if ( $_FILES[$fld]['error'] == 0 ) {
		$_POST['result']  = "アップロードに成功しました";
	}
	else {
		$_POST['result']  = "アップロードに失敗しました";
	}
}


$_POST['files'] = $_FILES;

// *************************************
// メール処理
// *************************************
mb_language("Japanese");
mb_internal_encoding("UTF-8");

$uniqid = uniqid();

$from_header = "From: " . mb_encode_mimeheader( mb_convert_encoding("差出人","iso-2022-jp") );

// このソースを置くサーバから使えるメールアドレス
$from_header .= " <{$GLOBALS["mail"]}>\n";
$from_header .= "Content-Type: multipart/mixed; boundary=\"{$uniqid}\"\n";

$mime = $_FILES['fld_file']['type'];
$fname = $_FILES['fld_file']['name'];

$body  = "--{$uniqid}\n";
$body .= "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n";
$body .= "\n";
$body .= $_POST['fld_body'] . "\n";
$body .= "--{$uniqid}\n";
$body .= "Content-Type: {$mime}; name=\"{$fname}\"\n";
$body .= "Content-Transfer-Encoding: base64\n";
$body .= "Content-Disposition: attachment; filename=\"{$fname}\"\n";
$body .= "\n";

// アップロードされたファイル
$path = $upload;
$data = file_get_contents($path);
$encode = base64_encode($data);

$body .= chunk_split($encode);
$body .= "\n--{$uniqid}--\n";

if ( !$GLOBALS["debug_update"] ) {
	$result = mb_send_mail(
		$_POST["fld_to"],
		$_POST["fld_subject"],
		$body,
		$from_header );
}
if ( $result ) {
	$error = 0;
}
else {
	$error = 1;
}

// アップロードして添付したファイルを削除
unlink($path);


// ***************************
// JSON データ作成
// ***************************
$json = new stdClass;

$json->post = $_POST;			// 行データ
$json->status = $error;		// エラー
if ( !$GLOBALS["debug_update"] ) {
	$json->user = $GLOBALS["mail"];
	$json->debug = $from_header;
}

print json_encode( $json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );

?>

関連する記事

fake sendmail for windows を使って、PHP でごく普通に( mb_send_mail で )メール送信 : Gmail なので ssl(465)




posted by lightbox at 2017-09-02 16:57 | Comment(0) | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

ファイルのアップロードからそれを添付してメールを送るテンプレート(スケルトン)



メール送信部分には、『mb_send_mail』を使用しているので、インターネット上のサーバーで、そこからパスワード無しでメールアドレスが利用できる必要があります。

※ fake sendmail for windows でも動作確認しました
※ FormData を使用して送信すると、ファイルのアップロードとメール送信を一度にできます。
( FormData を使用したサンプル )



メールアドレスは、mail.php で、セッション変数にセットして使用しています。

Content-Type の MIME は、ファイルアップロード時に取得した type をセッション変数に保存して使用しています。
<?php
require_once("common.php");

$_SESSION['user'] = "セッションデータを表示する為のダミー";
$_SESSION["mail_from"] = "メールアドレス";

require_once("mail_view.php");
?>
ファイル一覧
  • common.php
  • debug_value.php
  • mail.php
  • mail_view.php
  • form2.php
  • form2_view.php
  • upload1.php
  • html_head.php
  • mail_ex.php
  • style.css ※ ソース全体参照へのリンク
  • メール送信部分の mail_ex.php
    <?php
    require_once("common.php");
    
    require_once("html_head.php");
    
    foreach( $_POST as $Key => $Value ) {
    	$_POST[$Key] = str_replace("\\\\", "\\", $Value );
    	$_POST[$Key] = str_replace("\\'", "'", $_POST[$Key] );
    	$_POST[$Key] = str_replace("\\\"", "\"", $_POST[$Key] );
    }
    
    
    mb_language( "ja" );
    mb_internal_encoding("utf-8");
    
    $from = $_SESSION["mail_from"];
    $fname = $_SESSION["mail_file"];
    $mime = $_SESSION['mime'];
    
    if ( $fname == "" ) {
    	print "ファイルをアップロードして下さい <a href=\"mail.php\">戻る</a><br>";
    	exit();
    }
    
    $uniqid = uniqid();
    
    $headers = "From: {$from}\n";
    $headers .= "Content-Type: multipart/mixed; boundary=\"{$uniqid}\"\n";
    
    $body  = "--{$uniqid}\n";
    $body .= "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n";
    $body .= "\n";
    $body .= $_POST['text'] . "\n";
    $body .= "--{$uniqid}\n";
    $body .= "Content-Type: {$mime}; name=\"{$fname}\"\n";
    $body .= "Content-Transfer-Encoding: base64\n";
    $body .= "Content-Disposition: attachment; filename=\"{$fname}\"\n";
    $body .= "\n";
    
    $path = "upload_file/{$fname}";
    $data = file_get_contents($path);
    $encode = base64_encode($data);
    
    $body .= chunk_split($encode);
    $body .= "\n--{$uniqid}--\n";
    
    $ret = mb_send_mail(
    	$_POST['to_address'],
    	$_POST['subj'],
    	$body,
    	$headers );
    
    // アップロードして添付したファイルを削除
    unlink($path);
    $_SESSION["mail_file"] = "";
    
    if ( $ret === TRUE ) {
    	print "<a href=\"mail.php\">戻る</a> メール送信が終了しました。<br>";
    }
    else {
    	print "<a href=\"mail.php\">戻る</a> メール送信に失敗しました。<br>";
    }
    
    print "</body>";
    print "</html>";
    ?>
    
    
    ファイルのアップロード後、アップロードフォルダのファイルのタイムスタンプが5分以上経過している場合は削除します。(upload1.php)
    
    ファイルアップロードの実行は IFRAME 内の別ページで行っています。さらに、IFRAME 内の IFRAME にアップロード結果を表示している為、アップロード結果の『ファイル名』をメインページに転送する為、JavaScript を PHP で出力しています。
    
    その際、メインページでは jQuery を使用しているので、メインページの jQuery を使用してファイル名をテキストフィールドに転送しています
    
    if ( move_uploaded_file( $_FILES['file_1']['tmp_name'], $upload ) ) {
    	print "アップロードに成功しました<br>";
    	$_SESSION["mail_file"] = $target;
    	print "<script>";
    	print " parent.parent.$('#mail_file').val( \"{$target}\" );";
    	print "</script>";
    }
    else {
    	print "アップロードに失敗しました<br>";
    }
    
    
    関連する記事
    
    fake sendmail for windows を使って、PHP でごく普通に( mb_send_mail で )メール送信 : Gmail なので ssl(465)
    
    
    
    
    posted by lightbox at 2017-09-02 16:33 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    fake sendmail for windows を使って、PHP でごく普通に( mb_send_mail で )メール送信 : Gmail なので ssl(465)

    PHP : mb_send_mail を使用した自家用メール送信 API では、レンタルサーバー上利用する事を想定していましたが、fake sendmail for windows を使用すると、windows 上で同じ事ができます。
    
    fake sendmail は、XAMP に同梱されているらしい情報を多くインターネット上で得る事ができますが、何故か単独で Windows で利用する上では全く無名(日本)に近いソフトウェアのようです。
    
    メールサーバは、フリーメールで可能で、簡単な設定で利用できます。以下のサンプルは、Gmail で動作確認しました。( 但し、Gmail では、Gmail 側で安全性の低いアプリの許可を『有効』にする必要があります )
    
    ▼ 手順
    
    ダウンロード
    
    配布元より、sendmail.zip をダウンロードして、解凍します。
    
    
    sendmail.exe の動作テスト
    
    まず、sendmail.ini をエディタで開いて、四つのエントリを指定します
    ▼ Gmail の場合
    
    smtp_server=smtp.gmail.com
    smtp_port=465
    auth_username=ユーザ@gmail.com
    auth_password=パスワード
    
    ▼ さくらインターネットの場合
    smtp_server=初期ドメイン
    smtp_port=587
    auth_username=ユーザ@初期ドメイン
    auth_password=パスワード
    
    ※ smtp_ssl=auto となっており、デフォルトで ssl で実行され、使え無い場合は TLS を使おうとします さらに、この中に、send_test.bat を作成して以下のように記述します( 作者のオリジナルのテスト方法です )
    @ECHO OFF
    REM send email from command line via SMTP with sendmail
    
    ECHO From: ユーザ@gmail.com > %TEMP%\temp.mail
    ECHO To: ユーザ@宛先ドメイン >> %TEMP%\temp.mail
    ECHO Subject: this is a test >> %TEMP%\temp.mail
    ECHO.>> %TEMP%\temp.mail
    ECHO testing. >> %TEMP%\temp.mail
    ECHO blah blah.. >> %TEMP%\temp.mail
    ECHO. >> %TEMP%\temp.mail
    ECHO blah. >> %TEMP%\temp.mail
    
    sendmail -t < %TEMP%\temp.mail
    
    REM DEL %TEMP%\temp.mail
    
    
    これをコマンドプロンプトより実行して、メールが届く事を確認します。最後の行を REM でコメントにしているのは、送信で使われたテキストファイルを残す為です。sendmail.exe に -t が指定されているのは、標準入力より送信データを取得する為のもので、PHP で実行する場合特に必要はありませんでした。
    
    temp.mail の内容
    
    From: ユーザ@gmail.com 
    To: ユーザ@送り先ドメイン 
    Subject: this is a test 
    
    testing. 
    blah blah.. 
     
    blah. 
    
    これは、コマンドプロンプトから実行できる事を意味しますが、PHP で使用するには、php.ini で以下のように指定するだけです。 php.ini の設定
    sendmail_path = "C:\tools\sendmail\sendmail.exe"
    
    実際の sendmail.exe のパスを "" で囲んで指定します。 ※ この場合、エラーログは "C:\tools\sendmail\error.log" です( デフォルト ) PHP のコード
    mb_language("Japanese");
    mb_internal_encoding("UTF-8");
    
    $from_header = "From: " . mb_encode_mimeheader( mb_convert_encoding("差出人","iso-2022-jp") );
    
    // このソースを置くサーバから使えるメールアドレス
    $from_header .= " <{$GLOBALS["mail"]}>";
    
    $result = mb_send_mail($_POST["fld_to"], $_POST["fld_subject"], $_POST["fld_body"], $from_header);
    if ( $result ) {
    	$error = 0;
    }
    else {
    	$error = 1;
    }
    
    
    
    PHP の mb_send_mail の使用方法の全体のサンプルは、こちらを参照して下さい。
    
    
    
    
    posted by lightbox at 2017-09-02 13:36 | Comment(0) | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2017年06月27日


    ファイルを一つアップロード : FORM の target を IFRAME にして、PHP に JavaScript を書き出させて元のページにメッセージを表示させる

    昨今、ファイルをアップロードするならば、JavsScript を駆使して UI を作成し、 $.ajax で送信したほうが簡潔になりますが、ベタな FORM の記述のみで送信してそれなりのレスポンスを得ようという処理です。
    
    デモページ
    
    
    画像をクリックするとデモページへ移動します
    
    
    当然ですが、デモページで実際のアップロードはできません。しかし、結果を表示するにチェックを入れて送信すると、上の画像のように実際と同じ状態で情報をシミュレートします。
    
    UI の構築を気楽に工夫できるように、twitter-bootstrap の 4.0.0-alpha.6 を組み込んでいます
    
    IFRAME は本来非表示で、ここに JavaScript で右上のメッセージ(toastr.js)を表示するようにしていますが、デバッグ用としても使えるようにしており、その場合は PHP 側の $_FILES の中身が見れるようになっています。
    
    type="file" の name 属性は target で固定して php 側で使用しています。
    
    送信データの制限 データの制限はサーバに対する無意味なアクセスを遮断するアプローチと、アプリから見たデータの制限という二つのアプローチがあります。前者がもっとも重要で、それがなければ php.ini の upload_max_filesize 内であれば結果的にそのサイズまでは送信を許してしまいます。 ※ upload_max_filesize を超えると $_FILES そのものが空になるようです。 後者は、FORM 内の name="MAX_FILE_SIZE" の値で指定できますが、完全な対策ではありません。そこで、対象ページのあるディレクトリの .htaccess 内に 『LimitRequestBody 102400』のように制限値を設定し、さらに『ErrorDocument 413』 を設定してそのページの中でエラー処理の対応をしています ▼ 413.html
    <!DOCTYPE html>
    <html lang="ja">
    <style>
    * {
    	font-size: 32px;
    }
    </style>
    <script>
    
    	try {
    		parent.$("iframe").show();
    		parent.toastr.info( "ファイル のアップロードに失敗しました");
    		parent.toastr.info( "エラー内容 : Request Entity Too Large" );
    	}
    	catch (e) {}
    
    </script>
    </head>
    <body>
    
    JavaScript の処理用に IFRAME を定義している場合で、
    413 Request Entity Too Large が発生した場合にこのページが IFRAME 内に表示されます。
    
    </body>
    </html>
    
    
    
    file_upload_html.php
    
    $debug 変数で、実際のアップロードの可否を切り替えています。if ( !$_FILES ) { の部分は、upload_max_filesize を超えてしまった状態の対処ですが、ここでは LimitRequestBody 102400 を設定しているので発生する事はありません。
    
    <?php
    session_cache_limiter('nocache');
    session_start();
    
    header( "Content-Type: text/html; charset=utf-8" );
    
    // *************************************
    // 変数初期値
    // *************************************
    $debug = 0;
    $upload_dir = "./upload";
    if ( !$_FILES ) {
    	// php.ini の upload_max_filesize を超えて、
    	// Apache に制限が無いと $_FILE が空になる
    	$_FILES['target']['error'] = 5;	// ユーザエラーメッセージ
    }
    
    // *************************************
    // アップロード処理
    // フィールド名 : target で固定
    // *************************************
    if ( $_SERVER['REQUEST_METHOD'] == "POST" ) {
    
    	// 公開状態では実行しない
    	if ( $debug == 1 ) {
    
    		$upload = realpath ( $upload_dir );
    		$upload .= ( DIRECTORY_SEPARATOR . $_FILES['target']['name'] );
    		if ( move_uploaded_file(
    			$_FILES['target']['tmp_name'], $upload ) ) {
    			$_POST['result']  = "アップロードに成功しました";
    		}
    		else {
    			if ( !$_FILES ) {
    				$_FILES['target']['error'] = 5;	// ユーザエラーメッセージ
    			}
    			$_POST['result']  = "アップロードに失敗しました";
    		}
    
    	}
    	else {
    		if ( $_FILES['target']['error'] == 0 ) {
    			$_POST['result']  = "アップロードに成功しました";
    		}
    		else {
    			$_POST['result']  = "アップロードに失敗しました";
    		}
    	}
    
    }
    else {
    	$_POST['result']  = "POST メソッドを使用して下さい";
    }
    
    $_POST['files'] = $_FILES;
    
    // *************************************
    // この JSON 文字列を HTML 内の json
    // オブジェクト定義として埋め込みます
    // *************************************
    $json = json_encode($_POST, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );
    
    
    // *************************************
    // 画面定義
    // *************************************
    ?>
    <!DOCTYPE html>
    <html lang="ja">
    <script>
    var message = <?php require("error.json.php") ?>
    var json = <?= $json ?>;
    
    if ( json.files.target.error == 0 ) {
    	parent.toastr.info(json.files.target.name + " がアップロードされました");
    	parent.toastr.info("ファイルサイズ : " + json.files.target.size);
    }
    else {
    	parent.toastr.info(json.files.target.name + " のアップロードに失敗しました");
    	parent.toastr.info("エラー内容 : " + message.error[json.files.target.error]);
    }
    
    <?php if( $_POST["disp_result"] == "1" ) { ?>
    
    	parent.$("iframe[name='upload']")
    		.css("border", "1px solid #c0c0c0")
    		.show();
    
    <?php } else { ?>
    
    	parent.$("iframe[name='upload']").hide();
    
    <?php } ?>
    
    </script>
    </head>
    <body>
    <?php if( $_POST["disp_result"] == "1" ) { ?>
    <textarea style='width:90%;height:350px;'><?= $json ?></textarea>
    
    <?php } ?>
    </body>
    </html>
    
    
    
    error.json.php は、PHP のエラーメッセージです。ここでは部品として埋め込んでいますが、$.ajax バージョンでも使用(error.json.php?type=json)しています。
    
    error.json.php
    
    <?php
    if ( $_GET["type"] == "json" ) {
    	session_cache_limiter('nocache');
    	session_start();
    	header( "Content-Type: application/json; charset=utf-8" );
    }
    
    ?>
    {
    	"error": [
    		"0 - 正常終了",
    		"1 - アップロードされたファイルは、php.ini の upload_max_filesize ディレクティブの値を超えています",
    		"2 - アップロードされたファイルは、HTML フォームで指定された MAX_FILE_SIZE を超えています",
    		"3 - アップロードされたファイルは一部のみしかアップロードされていません",
    		"4 - ファイルはアップロードされませんでした",
    		"5 - 『アップロードに失敗しました』",
    		"6 - テンポラリフォルダがありません。PHP 5.0.3 で導入されました",
    		"7 - ディスクへの書き込みに失敗しました。PHP 5.1.0 で導入されました",
    		"8 - PHP の拡張モジュールがファイルのアップロードを中止しました"
    	]
    }
    
    
    
    upload.html
    
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="utf-8">
    <meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
    <title>HTML の FORM のみでファイルを一つアップロードする</title>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <link id="link" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.css">
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
    
    <!-- 共通の表示 -->
    <link rel="stylesheet" href="common.css">
    
    <!-- CSS の指定 -->
    <style>
    /* PC 用の表示 */
    @media screen and ( min-width:480px ) {
    	#content {
    		margin: 20px;
    	}
    }
    /* スマホ用の表示 */
    @media screen and ( max-width:479px ) {
    	#content {
    		margin: 0px;
    	}
    	body {
    		width: 100%!important;
    		margin: 0px;
    	}
    	.unit {
    		width: 100%;
    	}
    }
    </style>
    <script>
    // 簡易的なスマホチェックを jQuery のプロパティとして登録
    jQuery.isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
    if ( $.isMobile ) {
    	// スマホの場合は表示画面下の中央
    	toastr.options.positionClass = "toast-bottom-center";
    }
    
    $(function(){
    
    	// このページ自身の QRコードの表示
    	$('#qrcode')
    		.css({ "margin" : "20px" })
    		.qrcode({width: 160,height: 160,text: location.href });
    		
    
    });
    </script>
    </head>
    <body>
    <div id="head">
    	<div id="title">
    		<a href="./">One File アップロード</a>
    	</div>
    </div>
    
    <div id="content">
    
    	<form target="upload" enctype="multipart/form-data" action="../../php_upload/file_upload_html.php" method="POST">
    		<input type="hidden" name="MAX_FILE_SIZE" value="40000">
    		<input name="target" type="file" class="btn btn-info">
    		<input type="submit" value="ファイルを送信" class="btn btn-success ">
    
    		<br>
    		<label for="disp_result">結果を表示する</label> <input id="disp_result" type="checkbox" name="disp_result" value="1" class="mt-5">
    	</form>
    
    </div>
    
    <div id="qrcode"></div>
    
    <iframe src="about:blank" name="upload" style="display:none;border:0px solid #c0c0c0;margin-left:20px;width:90%;height:400px;"></iframe>
    
    
    
    </body>
    </html>
    
    
    
    HTML 側のダウンロード
    
    
    
    PHP 側のダウンロード
    
    
    
    
    
    
    posted by lightbox at 2017-06-27 12:55 | Comment(0) | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2017年05月29日


    PHP : MastodonOAuthPHP の HttpRequest.php の http_request を public に書き換えて、ファイルアップロード

    MastodonOAuthPHP
    
    HttpRequest.php の http_request は、file_get_contents を使用した通信処理です。とてもいいサンプルですし、ソースも簡単に読めます。HttpRequest.php のみ upload_file.php と同じディレクトリに置いて実行します。
    
    以下は http_request メソッドを public にして普通に使えるサンプルです。
    
    upload_file.php
    
    <?php
    session_cache_limiter('nocache');
    session_start();
    
    header( "Content-Type: text/html; charset=utf-8" );
    
    // **********************************************
    // クラス定義の読み込み
    // **********************************************
    require_once("HttpRequest.php");
    
    // **********************************************
    // 【クラスの参照】
    // HttpRequest の別名を Http として使用
    // **********************************************
    use \theCodingCompany\HttpRequest as Http;
    
    $file_name = "./img.jpg";
    
    $data = file_get_contents($file_name);
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_buffer($finfo, $data);
    finfo_close($finfo);
    
    $body = <<<DATA
    -----------------------------7da1c519203ca
    Content-Disposition: form-data; name="target"; filename="img.jpg"
    Content-Type: {$mime}
    
    {$data}
    -----------------------------7da1c519203ca
    Content-Disposition: form-data; name="send"
    
    送信
    -----------------------------7da1c519203ca--
    DATA;
    
    // バイト数
    $size = strlen($body);
    
    $header = array(
    	"Content-Type" => "multipart/form-data; boundary=---------------------------7da1c519203ca",
    	"Content-Length" => $size
    );
    
    // **********************************************
    // アップロード
    // **********************************************
    $result = Http::http_request(
    	"POST",
    	"https://ドメイン/demo/file_upload.php", 
    	$header, 
    	$body
    );
    
    print_r( $result );
    
    ?>
    
    
    ※ データ区切りの boundary は、以前にダンプした実データのものを使用しています。
    ※ name="target" でアップロードしています。なので、受けの PHP では固定で処理しました。
    
    file_upload.php
    
    <?php
    session_cache_limiter('nocache');
    session_start();
    
    header( "Content-Type: application/json; charset=utf-8" );
    
    
    if ( $_SERVER['REQUEST_METHOD'] == "POST" ) {
     
    	$upload = realpath ( './image' );
    	$upload .= ( DIRECTORY_SEPARATOR . $_FILES['target']['name'] );
    	if ( move_uploaded_file(
    		$_FILES['target']['tmp_name'], $upload ) ) {
    		$_POST['result']  = "アップロードに成功しました";
    	}
    	else {
    		$_POST['result']  = "アップロードに失敗しました";
    	}
    
    }
    else {
    	$_POST['result']  = "POST メソッドを使用して下さい";
    }
    
    $_POST['files'] = $_FILES;
    
    print json_encode($_POST, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE );
    ?>
    
    
    
    関連する記事
    
    MastodonOAuthPHP の HttpRequest.php の解説
    
    WindowBuilder(Swing) で、WEBカメラを使用して画像を保存して okhttp で WEBサーバへアップロードする
    
    
    
    
    タグ:通信 PHP
    posted by lightbox at 2017-05-29 23:52 | Comment(0) | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2017年05月03日


    MastodonOAuthPHP の HttpRequest.php の解説

    MastodonOAuthPHP の HttpRequest.php は、Mastodon 用というか、API 呼び出しに特化しているので、そのまま使うには少し改造が必要です。ですが、GET 呼び出しはとりあえずそのまま使えるので、仕様としての概要をだいたいは知る事ができます。
    
    get_and_save.php
    
    <?php
    session_cache_limiter('nocache');
    session_start();
    
    header( "Content-Type: text/html; charset=utf-8" );
    
    // **********************************************
    // クラス定義の読み込み
    // **********************************************
    require_once("HttpRequest.php");
    
    // **********************************************
    // 【クラスの参照】
    // HttpRequest の別名を MastodonHttp として使用
    // **********************************************
    use \theCodingCompany\HttpRequest as MastodonHttp;
    
    $path = "0502/std.html";
    
    // **********************************************
    // ペース URL を設定をしたインスタンスの取得
    // **********************************************
    $http = MastodonHttp::Instance("http://localhost");
    
    // **********************************************
    // static メソッドの実行
    // **********************************************
    $result = $http::Get($path);
    
    
    
    file_put_contents('get_and_save.txt', $result );
    
    ?>
    保存しました
    
    
    
    クラスの参照
    
    まず、HttpRequest クラスは名前空間が theCodingCompany で定義されているので、require_once で読み込んだ後、use \theCodingCompany\HttpRequest as MastodonHttp; で、MastodonHttp という名前で使えるようにします。
    
    ※ 別名を定義する必要は無いのですが、use \theCodingCompany\HttpRequest は参照するのに必要です。
    
    コンストラクタが protected
    
    使い勝手の理由だと思いますが、new でインスタンスを作らずに instance メソッドを実装してインスタンスを作成するようになっています。内部メソッドは全て static なので、インスタンス化しなくても呼べるはずですが、API 用の $base_url と $base_path を保存した上で インスタンス化して使用しています。
    
    ※ インスタンス化されたクラスオブジェクトから static なメソッドにはアクセスできます
    
    static 仕様にした本当の理由は解りませんが、get_called_class を使用して呼び出し元からの インスタンス作成で必ず再利用できるようになっているようです。( instance メソッド を何度読んでも一度しか作成されないので、結果的には static メソッドのクラスを使うのと同じようになっています )
    
    コンストラクタと instance メソッド
    
        // コンストラクタ
        protected function __construct($base_url = "", $base_path = "/") {            
            self::$base_path = $base_path;
            self::$base_url = $base_url;
        }
        
        // インスタンス作成用メソッド
        public static function Instance($base_url = "", $base_path = "/"){
            $cls = get_called_class();
            if(!isset(self::$instance[$cls])){
                self::$instance[$cls] = new HttpRequest($base_url, $base_path);
            }
            return self::$instance[$cls];
        }
    
    
    
    結果的に $http::Get($path); は、$http がインスタンスで、インスタンスから static メソッドを呼び出しています。
    
    Post メソッドは API に特化
    
        public static function Post($path = "", $parameters = array(), $headers = array()){
            //Sen the request and return response
            $post_data = json_encode($parameters);
            return self::http_request(
                "POST", 
                self::$base_url.self::$base_path.$path, 
                $headers,
                $post_data
            );
        }
    
    
    データ部分が JSON フォーマットに固定されています。このままでは一般用では使用できないのですが、private メソッドの http_request が結果的に一般仕様なので、これを public に変更すると使えるはずです。
    
    http_request を public にして使用 
    
    public で、URL は直接指定なので、インスタンス作成する必要もありません。
    
    <?php
    session_cache_limiter('nocache');
    session_start();
    
    header( "Content-Type: text/html; charset=utf-8" );
    
    // **********************************************
    // クラス定義の読み込み
    // **********************************************
    require_once("HttpRequest.php");
    
    // **********************************************
    // 【クラスの参照】
    // HttpRequest の別名を MastodonHttp として使用
    // **********************************************
    use \theCodingCompany\HttpRequest as MastodonHttp;
    
    // **********************************************
    // POST
    // **********************************************
    MastodonHttp::http_request("POST","http://localhost/0502/post_and_save.php", array(), array( "text" => "投稿データ" ) );
    
    ?>
    投稿しました
    
    
    
    
    
    posted by lightbox at 2017-05-03 20:58 | Comment(0) | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2015年11月05日


    PHP : mb_send_mail を使用した自家用メール送信 API

    連想配列のキー部分がプロパティと一致したらセットする( メール送信用クラス ) では、$_GET でメール用のクラスのテストを行いましたが、実際にレンタルサーバに置いて、自分専用の API として整備しました。
    
    ブラウザからも直接使えるように、header( "Access-Control-Allow-Origin: *" ); を実行しています。
    
    自分専用ですが、イザという時に全て遮断できるように簡易パスワードを設定してあります。
    
    呼び出し側は POST で送信して、FORM 要素を使用する場合は、name の値を クラスのプロパティと一致させるだけで利用可能です。( 但し差出人のメールアドレスは仕様上固定です )
    
    
    { "error": "nothing" } は、正常終了です
    
    <?php
    header( "Content-Type: application/json; Charset=utf-8" );
    header( "pragma: no-cache" );
    header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
    header( "Cache-control: no-cache" );
    header( "Access-Control-Allow-Origin: *" );
    
    mb_language( "ja" );
    mb_internal_encoding("utf-8");
    
    if ( $_POST['pass'] != "簡易パスワード" ) {
    	print '{ "error": "no pass" }';
    	exit();
    }
    
    $mail = new mail_data();
    
    $_POST['from_address'] = "サーバ側で認証の必要の無いメールアドレス";
    
    $mail->send_mail_set($_POST);
    
    $result = $mail->send_mail();
    
    if ( $result ) {
    	print '{ "error": "nothing" }';
    }
    else {
    	print '{ "error": "mb_send_mail" }';
    }
    
    // ***********************************************
    // メール処理用クラス
    // ***********************************************
    class mail_data {
    
    	public $from_address;
    	public $from_text;
    	public $to_address;
    	public $to_text;
    	public $subject;
    	public $body;
    
    	// ***********************************************
    	// 連想配列のキー部分がプロパティと一致したらセット
    	// ***********************************************
    	public function send_mail_set( $data ) {
    
    		foreach( $data as $k => $v ) {
    			if ( property_exists( $this, $k ) ) {
    				$this->{$k} = $v;
    			}
    		}
    
    	}
    
    	// ***********************************************
    	// サーバー(メールサーバ)送信処理
    	// ***********************************************
    	public function send_mail() {
    
    		$from = mb_convert_encoding( $this->from_text, "JIS", "utf-8" );
    		$from = "From: =?ISO-2022-JP?B?" . base64_encode($from) . "?= <{$this->from_address}>";
    		$to = mb_convert_encoding( $this->to_text, "JIS", "utf-8" );
    		$to = "=?ISO-2022-JP?B?" . base64_encode($to) . "?= <{$this->to_address}>";
    		return mb_send_mail($to, $this->subject, $this->body, $from );
    	}
    
    }
    ?>
    
    
    
    ブラウザからの ajax を想定していますが、以下は FORM による 直接テスト用の画面になります
    
    send_test.php
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css">
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
    
    <style>
    .title {
    	display: inline-block;
    	width: 150px;
    	padding: 15px;
    }
    
    .entry {
    	display: inline-block;
    	width: 350px;
    	padding: 15px;
    }
    
    </style>
    <script>
    // jQuery 初期処理
    $(function() {
    
    	$("input,textarea").prop("required", true );
    
    });
    </script>
    </head>
    <body>
    <div>
    
    <?php
    // -------------------------------------
    // フォーム開始
    // -------------------------------------
    ?>
    <form 
    	method="post"
    	action="send_mail.php"
    	target="_self">
    <?php
    // -------------------------------------
    // 簡易パスワード
    // -------------------------------------
    ?>
    <input 
    	type="hidden"
    	name="pass"
    	value="簡易パスワード">
    
    
    <div class="title">差出人(日本語)</div>
    <div class="entry">
    	<input
    		type="text"
    		name="from_text"
    		maxlength="50"
    		style="width:200px">
    </div>
    
    <br>
    
    <div class="title">宛先</div>
    <div class="entry">
    	<input
    		type="text"
    		name="to_address"
    		style="width:200px">
    </div>
    
    <br>
    
    <div class="title">宛先(日本語)</div>
    <div class="entry">
    	<input
    		type="text"
    		name="to_text"
    		style="width:200px">
    </div>
    
    <br>
    
    <div class="title">件名</div>
    <div class="entry">
    	<input
    		type="text"
    		name="subject"
    		style="width:200px">
    </div>
    
    <br>
    
    <div class="title" style='vertical-align:top'>本文</div>
    <div class="entry">
    	<textarea
    		name="body"
    		style="width:200px;height:150px;"></textarea>
    </div>
    
    <br>
    
    
    <div class="title"></div>
    <div class="entry">
    	<input
    		type="submit"
    		name="send"
    		value="送信">
    </div>
    
    </form>
    
    </body>
    </html>
    
    
    
    
    
    
    posted by lightbox at 2015-11-05 21:39 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    Windows PHP(Pear)で、Gmail(SSL/465)を使ってメールを送る

    ※ 重要
    アプリが正しくても、サーバーでログインを拒否されている場合があります。実際問題、WEBブラウザでログインしに行くと、難読文字画像で認証をされられた事が Hotmail ではありました。Google でも同様の事があると他の記事で読んだ事があるので注意して下さい。
    
    Gmail 側で安全性の低いアプリの許可を『有効』にする必要がありました。
    
    
    Pear なんで、WEBサーバー(Unix等)でも動くと思いますが、その場合はWEBサーバ用のメールアドレスで sendmail が使えると思います。なので、わざわざ Pear を使う必要は無いですが、フリーの WEBサーバだと、sendmail は使え無いのでその時は試してみる価値はあります。
    
    Windows でPHPからメールを送信するには Pear が必要です。( もう一つの選択肢として、CDO.Message を使う事もできます )
    
    あるいは、fake sendmail for windows を使用できます
    
    (1) php.ini の OpenSSL を有効にする
    
    extension=php_openssl.dll
    
    (2) php.ini の error_reporting に STRICT エラー用の設定を行う
    error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT
    
    ※ ソースで error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT); でも可 (3) Pear の関係ファイルをダウンロード Pear
    PEAR.php だけでいいです
    
    Mail
    Mail フォルダと、Mail.php
    
    Net_SMTP
    SMTP.php ( Net ディレクトリ内 )
    
    Net_Socket
    Socket.php ( Net ディレクトリ内 )
    
    Net_SMTP の中に以下のようなコメントがあります
         * If you have SSL support in PHP, you can connect to a server
         * over SSL using an 'ssl://' prefix:
         *
         *   // 465 is a common smtps port.
         *   $smtp = new Net_SMTP('ssl://mail.host.com', 465);
         *   $smtp->connect();
    
    send_test.php(UTF-8N で保存)
    <?php
    error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);
    
    header( "Content-Type: text/html; Charset=utf-8" );
    header( "pragma: no-cache" );
    header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
    header( "Cache-control: no-cache" );
    
    require_once("Mail.php");
    
    mb_language("ja");
    mb_internal_encoding("UTF-8");
    
    // ***********************************************
    // 通信のデバッグ表示
    // ***********************************************
    $debug = true;
    
    // ***********************************************
    // SMTP 接続設定
    // ***********************************************
    $settings = array(
    	"host"		=> "ssl://smtp.gmail.com",
    	"port"		=> "465",
    	"auth"		=> true,
    	"username"	=> "ユーザ名@gmail.com",
    	"password"	=> "パスワード",
    	"debug"		=> $debug
    );
    
    // ***********************************************
    // メールアドレス
    // ***********************************************
    $to_address = "宛先メールアドレス";
    $from_address = "ユーザ名@gmail.com";
    
    // ***********************************************
    // メールヘッダー
    // ***********************************************
    $subject = "Gmail(SSL/465)を使ってPHPでメールを送る";
    $subject = mb_encode_mimeheader( mb_convert_encoding($subject,"iso-2022-jp") );
    
    $to_header =  mb_encode_mimeheader( mb_convert_encoding("宛先","iso-2022-jp") ) . " <{$to_address}>";
    $from_header =  mb_encode_mimeheader( mb_convert_encoding("差出人","iso-2022-jp") ) . " <{$from_address}>";
    
    $headers = array(
    	"To"		=> $to_header,
    	"From"		=> $from_header,
    	"Subject"	=> $subject
    );
    
    // ***********************************************
    // 本文
    // ***********************************************
    $body="本文";
    $body = mb_convert_encoding($body,"iso-2022-jp");
    
    // ***********************************************
    // SMTP 接続設定をオブジェクトに設定
    // ***********************************************
    $smtp = Mail::factory("smtp", $settings);
    
    // ***********************************************
    // 送信
    // ***********************************************
    print "<pre>"; 
    $result = $smtp->send(
    	$to_address,
    	$headers,
    	$body );
    print "</pre>"; 
    
    if ( PEAR::isError($result) ) {
    	print "メール送信エラー:" . $result->getMessage();
    }
    
    ?>
    OK
    
    
    ※ Debug フラグを true にしているので、トレースが出力されます
    
    ▼ 以下は関数にしたものです
    
    // ***********************************************
    // メール送信
    // ***********************************************
    function send_mail($user,$to,$pass,$message,$subject) {
    
    	global $ErrorMessage;
    
    	error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);
    
    	// この場合は実行する PHP と同じフォルダに Mail.php があるという前提です
    	// それ以外の場合は、
    	// set_include_path( get_include_path() . PATH_SEPARATOR . "Mail.phpのあるフォルダ" );
    	// を実行します
    	require_once("Mail.php");
    
    	mb_language("ja");
    	mb_internal_encoding("UTF-8");
    	
    	// ***********************************************
    	// 通信のデバッグ表示
    	// ***********************************************
    	$debug = false;
    	
    	// ***********************************************
    	// SMTP 接続設定
    	// ***********************************************
    	$settings = array(
    		"host"		=> "ssl://smtp.gmail.com",
    		"port"		=> "465",
    		"auth"		=> true,
    		"username"	=> $user,
    		"password"	=> $pass,
    		"debug"		=> $debug
    	);
    	
    	// ***********************************************
    	// メールアドレス
    	// ***********************************************
    	$to_address = $to;
    	$from_address = $user;
    	
    	// ***********************************************
    	// メールヘッダー
    	// ***********************************************
    	$subject = mb_encode_mimeheader( mb_convert_encoding($subject,"iso-2022-jp") );
    	
    	$to_header =  mb_encode_mimeheader( mb_convert_encoding("宛先","iso-2022-jp") ) . " <{$to_address}>";
    	$from_header =  mb_encode_mimeheader( mb_convert_encoding("差出人","iso-2022-jp") ) . " <{$from_address}>";
    	
    	$headers = array(
    		"To"		=> $to_header,
    		"From"		=> $from_header,
    		"Subject"	=> $subject
    	);
    	
    	// ***********************************************
    	// 本文
    	// ***********************************************
    	$body=$message;
    	$body = mb_convert_encoding($body,"iso-2022-jp");
    	
    	// ***********************************************
    	// SMTP 接続設定をオブジェクトに設定
    	// ***********************************************
    	$smtp = Mail::factory("smtp", $settings);
    	
    	// ***********************************************
    	// 送信
    	// ***********************************************
    	print "<pre>"; 
    	$result = $smtp->send(
    		$to_address,
    		$headers,
    		$body );
    	print "</pre>"; 
    	
    	if ( PEAR::isError($result) ) {
    		// print "メール送信エラー:" . $result->getMessage();
    		$ErrorMessage = "メール送信エラー:" . $result->getMessage();
    	}
    
    	
    
    }
    
    
    
    
    posted by lightbox at 2015-11-05 21:38 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2015年10月03日


    PHP で Windows標準のオブジェクト(CDO.Message)とGMail を使ってメール送信

    ひさしぶりにテスト( Windows7 ) しようとすると、Gmail からエラーが返って来ましたが、Gmail 側で安全性の低いアプリの許可を『有効』にする必要がありました。
    
    また、php 側では、php_com_dotnet.dll を php.ini で有効にする必要があります。
    
    ※ CDO.Message に関する詳細は、ソース内に URL を記述しています
    
    関連する記事
    
    Windows標準のオブジェクト(CDO.Message)とGMail を使ってメール送信
    
    本来は、VBScript で実行するものですが、PHP が分かる人なら、こちらのほうがいろいろ応用がきいて使い勝手もいいと思います。
    
    ▼ バッチファイル
    ------------------------------------------------------
    @echo off
    setlocal
    set PATH=c:\php;%PATH%
    
    php mail.php "題名" "本文\nで す\nよ"
    
    endlocal
    ------------------------------------------------------
    
    mail.php
    
    <?php
    // ***********************************************
    // バッチファイル内容
    // setlocal は、環境変数を一時的に設定する為に使用します
    // php.exe は、c:\php にあります
    // ***********************************************
    /*
    @echo off
    setlocal
    set PATH=c:\php;%PATH%
    
    php mail.php "題名" "本文\nで す\nよ"
    
    endlocal
    */
    
    // ***********************************************
    // php.ini で必要な拡張
    // ***********************************************
    /*
    extension=php_com_dotnet.dll
    */
    
    // ***********************************************
    // Gmail 側の設定
    // ***********************************************
    /*
    安全性の低いアプリの許可を『有効』にする
    
    https://myaccount.google.com/security?pli=1#connectedapps
    */
    
    // ***********************************************
    // PHP の処理開始
    // ***********************************************
    $strFrom = "私です <ユーザ名@gmail.com>";
    $strTo = "あなたです <宛先メールアドレス>";
    
    $strServer = "smtp.gmail.com";
    $nPort = 465;
    $strUser = "ユーザ名@gmail.com";
    $strPass = "パスワード!";
    
    // ***********************************************
    // CDO.Message( CDO for Windows 2000 )
    // ***********************************************
    $cdo = new COM( "CDO.Message" );
    
    $cdo->From = $strFrom;
    $cdo->To = $strTo;
    
    // ***********************************************
    // 題名
    // ***********************************************
    $cdo->Subject = $argv[1];
    
    // ***********************************************
    // バッチファイルで引渡した本文文字列内の \n を実際の改行に変換
    // ***********************************************
    $data = str_replace( "\\n", "\n", $argv[2] );
    $cdo->Textbody = $data;
    
    // ***********************************************
    // 送信情報オプション
    // ***********************************************
    $cdo->Cc = "メールアドレス1,メールアドレス2";
    //$cdo->Bcc = "";
    $cdo->Htmlbody = "<img src=\"http://winofsql.jp/image/winofsql.png\">";
    
    // ***********************************************
    // ファイル添付
    // ***********************************************
    $cdo->AddAttachment( "C:\\Users\\lightbox\\Desktop\\画像\\_img.jpg" );
    
    // cdoSendUsingPort : 2 : Send the message using the network (SMTP over the network)
    // https://msdn.microsoft.com/en-us/library/ms527265.aspx.
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"] = 2;
    
    // The name (DNS) or IP address of the machine hosting the SMTP service through which messages are to be sent.
    // https://msdn.microsoft.com/en-us/library/ms527294.aspx
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/smtpserver"] = $strServer;
    
    // The port on which the SMTP service specified by the smtpserver field is listening for connections.
    // https://msdn.microsoft.com/en-us/library/ms526227.aspx
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"] = $nPort;
    
    // Indicates that SSL should be used when sending messages using the SMTP protocol over the network.
    // https://msdn.microsoft.com/en-us/library/ms526975.aspx
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/smtpusessl"] = true;
    
    // Specifies the authentication mechanism to use when authentication is required to send messages
    // to an SMTP service using a TCP/IP network socket.
    // https://msdn.microsoft.com/en-us/library/ms526600.aspx
    // 1 : Use basic (clear-text) authentication
    // https://msdn.microsoft.com/en-us/library/ms526961.aspx
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"] = 1;
    
    // ユーザとパスワード
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/sendusername"] = $strUser;
    $cdo->Configuration->Fields["http://schemas.microsoft.com/cdo/configuration/sendpassword"] = $strPass;
    
    $cdo->Configuration->Fields->Update();
    
    $cdo->Send();
    
    // ***********************************************
    // レジストリ内容
    // ***********************************************
    /*
    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\CLSID\{CD000001-8B95-11D1-82DB-00C04FB1625D}]
    @="CDOMessage Class"
    
    [HKEY_CLASSES_ROOT\CLSID\{CD000001-8B95-11D1-82DB-00C04FB1625D}\InprocServer32]
    @="C:\\Windows\\system32\\cdosys.dll"
    "ThreadingModel"="Both"
    
    [HKEY_CLASSES_ROOT\CLSID\{CD000001-8B95-11D1-82DB-00C04FB1625D}\ProgID]
    @="CDO.Message.1"
    
    [HKEY_CLASSES_ROOT\CLSID\{CD000001-8B95-11D1-82DB-00C04FB1625D}\Programmable]
    
    [HKEY_CLASSES_ROOT\CLSID\{CD000001-8B95-11D1-82DB-00C04FB1625D}\VersionIndependentProgID]
    @="CDO.Message"
    */
    ?>
    
    
    参考情報
    
    メーラーからGmailへの接続時に認証(パスワード)のエラーが生じる場合の対処方法
    
    
    
    
    posted by lightbox at 2015-10-03 21:44 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2015年06月22日


    PHP : http 経由でファイルのサイズを取得する file_size 関数と ファイルサイズを付加した get_imagesize 関数

    getimagesize は、ファイルのサイズが取得されません。あまり大きいサイズは事前に排除したいので、ファイルサイズを付加すれば便利だろうと思い、まず file_size 関数を作成しました。
    
    
    
    ※ getimagesize( get_imagesize ) は、画像以外だとエラーになります。
    
    <?php
    header( "Content-Type: text/html; Charset=utf-8" );
    header( "pragma: no-cache" );
    header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
    header( "Cache-control: no-cache" );
    
    if ( $_SERVER["REQUEST_METHOD"] == "POST" ) {
    
    	if ( $_POST["send"] == "テスト送信" ) {
    		$result = @getimagesize( $_POST["url"] );
    		if ( $result !== false ) {
    			$view = print_r( $result, true );
    
    			$header = get_headers( $_POST["url"] );
    			$view .= print_r( $header, true );
    
    			$size = implode( "\n", $header );
    			$view .= $size;
    
    			if (preg_match('/Content-Length: (\d+)/', $size, $matches)) {
    				$contentLength = (int)$matches[1];
    				$view .= "\n\niamge size : {$contentLength}";
    			}
    
    		}
    		else {
    			$view = "{$_POST["url"]} を読み込めません";
    		}
    	}
    
    	if ( $_POST["send"] == "get_imagesize" ) {
    		$result = get_imagesize( $_POST["url"] );
    		if ( $result !== false ) {
    			$view = print_r( $result, true );
    		}
    		else {
    			$view = "{$_POST["url"]} を読み込めません";
    		}
    	}
    
    	if ( $_POST["send"] == "fle_size" ) {
    		$result = fle_size( $_POST["url"] );
    		if ( $result !== false ) {
    			$view = "filesize : $result";
    		}
    		else {
    			$view = "{$_POST["url"]} を読み込めません";
    		}
    	}
    }
    
    function get_imagesize($url) {
    
    	$result = @getimagesize($url);
    	if ( $result !== false ) {
    		$view = print_r( $result, true );
    
    		$size = fle_size($url);
    		if ( $size !== false ) {
    			$result["size"] = $size;
    		}
    		return $result;
    	}
    	else {
    		return false;
    	}
    
    }
    
    function fle_size($url) {
    
    	$header = @get_headers($url) ;
    	if ( $header !== false ) {
    		$size = implode( "\n", $header );
    		if (preg_match('/Content-Length: (\d+)/', $size, $matches)) {
    			$contentLength = (int)$matches[1];
    			return $contentLength;
    		}
    		else {
    			return false;
    		}
    	}
    	else {
    		return false;
    	}
    
    }
    
    ?>
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <style>
    * {
    	font-size: 16px;
    	font-family: "Hiragino Kaku Gothic ProN", "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
    }
    </style>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script>
    $(function(){
    
    });
    </script>
    </head>
    <body>
    
    <form method="post" target="_self">
    	URL => <input type="text" name="url" style="width:800px;" value="<?= $_POST["url"] ?>">
    	<br>
    
    	<input type="submit" name="send" value="テスト送信">
    	<input type="submit" name="send" value="get_imagesize">
    	<input type="submit" name="send" value="fle_size">
    </form>
    <pre>
    <?= $view ?>
    </pre>
    </body>
    </html>
    
    
    ※ ボタン画像
    
    
    
    posted by lightbox at 2015-06-22 14:26 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2015年05月15日


    連想配列のキー部分がプロパティと一致したらセットする( メール送信用クラス )

    ▼ 以下の記事のメール送信部分に汎用性を持たせる為に、作成しました。ブラウザからは、FORM で直接呼び出してもいいですが、jQuery で .serialize() から .post() を使用する方法もあります。
    
    @BBS(アットビービーエス) のサービスが終了するので、管理人宛のメールサービスをほぼ同じ画面デザインで作成しました。( ご自由にお使い下さい )
    
    UTF-8 前提です
    
    <?php
    
    mb_language( "ja" );
    mb_internal_encoding("utf-8");
    
    $mail = new mail_data();
    
    $_GET['from_address'] = "このPHPが置かれるサーバで使用できるメールアドレス";
    $_GET['from_text'] ="日本語差出人";
    $_GET['to_address'] ="送り先のメールアドレス";
    $_GET['to_text'] ="日本語受取人";
    $_GET['subject'] ="件名";
    $_GET['body'] ="本文1\n本文2\n";
    
    $_GET['another'] ="その他";
    
    $mail->send_mail_set($_GET);
    
    print "<pre>";
    print_r($mail);
    print "</pre>";
    
    $mail->send_mail();
    
    // ***********************************************
    // メール処理用クラス
    // ***********************************************
    class mail_data {
    
    	public $from_address;
    	public $from_text;
    	public $to_address;
    	public $to_text;
    	public $subject;
    	public $body;
    
    	// ***********************************************
    	// 連想配列のキー部分がプロパティと一致したらセット
    	// ***********************************************
    	public function send_mail_set( $data ) {
    
    		foreach( $data as $k => $v ) {
    			if ( property_exists( $this, $k ) ) {
    				$this->{$k} = $v;
    			}
    		}
    
    	}
    
    	// ***********************************************
    	// サーバー(メールサーバ)送信処理
    	// ***********************************************
    	public function send_mail() {
    
    		$from = mb_convert_encoding( $this->from_text, "JIS", "utf-8" );
    		$from = "From: =?ISO-2022-JP?B?" . base64_encode($from) . "?= <{$this->from_address}>";
    		$to = mb_convert_encoding( $this->to_text, "JIS", "utf-8" );
    		$to = "To: =?ISO-2022-JP?B?" . base64_encode($to) . "?= <{$this->to_address}>";
    		mb_send_mail($to, $this->subject, $this->body, $from );
    	}
    
    }
    
    ?>
    
    
    $_GET を使っているのは、テスト段階なのが理由です。実装では $_POST が望ましいです。
    
    
    
    posted by lightbox at 2015-05-15 17:14 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    @BBS(アットビービーエス) のサービスが終了するので、管理人宛のメールサービスをほぼ同じ画面デザインで作成しました。( ご自由にお使い下さい )

    デモページ
    
    
    フォントは変更し、必要無い文言は削除しています。
    ( オリジナルは SHIFT_JIS でしたが、全て UTF-8 に変更しました )
    
    
    
    自分が管理するサーバー(レンタルサーバー)があって、そのサーバーから PHP の mb_send_mail 関数で呼び出す事のできるメールアカウントを使って利用可能です。
    
    common.php
    
    <?php
    header( "Content-Type: text/html; Charset=utf-8" );
    header( "pragma: no-cache" );
    header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
    header( "Cache-control: no-cache" );
    
    mb_language( "ja" );
    mb_internal_encoding("utf-8");
    
    function admin_mail( $user_body, $user_mail, $user_subject ) {
    	$from_address = "<このPHPが置かれるサーバで使用できるメールアドレス>";
    	$from = "日本語の差出人";
    	$to_address = "<管理人のメールアドレス>";
    	$to = "管理人宛";
    
    	$from = mb_convert_encoding( $from, "JIS", "utf-8" );
    	$from	= "From: =?ISO-2022-JP?B?" . base64_encode($from) . "?= $from_address";
    	$to = mb_convert_encoding( $to, "JIS", "utf-8" );
    	$to	= "To: =?ISO-2022-JP?B?" . base64_encode($to) . "?= $to_address";
    
    	$mail_body = "------------------------------------------------\n";
    	$mail_body .= "(注)このメールに直接返信しないでください。\n";
    	$mail_body .= "送信元は投稿者ではありません。\n";
    	$mail_body .= "下記掲載の「投稿者のメールアドレス」に返信してください。\n";
    	$mail_body .= "------------------------------------------------\n";
    	$mail_body .= "投稿者のIP:{$_SERVER["REMOTE_ADDR"]}\n";
    	$mail_body .= "投稿者のメールアドレス:{$user_mail}\n";
    	$mail_body .= "内容:\n";
    	$mail_body .= $user_body;
    
    	mb_send_mail($to, $user_subject, $mail_body, $from );
    
    }
    ?>
    
    
    カスタマイズしやすいように、画面処理は 3つ の PHP ファイルで遷移させています。
    
    1) 入力 : adminmail_1.php
    2) 確認 : adminmail_2.php
    3) 終了 : adminmail_3.php
    
    その為、通常のデータの受け渡しは、POST を使用していますが、エラー処理の画面遷移では GET を使用しています。
    
    セッションを使うともっと簡潔になりますが、ここでは使用していません。
    
    adminmail_1.php
    
    このページに サーバーから $_POST が送られる事はありませんが、画面遷移を1つのページに仕様変更する際には必要なので、便宜上記述しています。
    
    str_replace の処理は、入力値を HTML 内に問題無く埋め込めるようにする為に、HTML の < と > と 属性の値に使われる "(ダブルクォーテーション) を変換しています。
    
    <?php
    require_once( "common.php" );
    
    foreach($_POST as $k => $v) {
    	$v = str_replace("\"","&#34;",$v);
    	$v = str_replace("<","&lt;",$v);
    	$_POST[$k] = str_replace(">","&gt;",$v);
    }
    foreach($_GET as $k => $v) {
    	$v = str_replace("\"","&#34;",$v);
    	$v = str_replace("<","&lt;",$v);
    	$_GET[$k] = str_replace(">","&gt;",$v);
    }
    
    $message = "";
    if ( $_GET['e1'] == "1" ) {
    	$message .= "<br>※ 件名を入力してください";
    }
    if ( $_GET['e2'] == "1" ) {
    	$message .= "<br>※ メールアドレスを入力してください";
    }
    if ( $_GET['e2'] == "2" ) {
    	$message .= "<br>※ メールアドレスが正しく無いようです";
    }
    if ( $_GET['e3'] == "1" ) {
    	$message .= "<br>※ 本文を入力して下さい";
    }
    
    if ( $message != "" ) {
    	foreach($_GET as $k => $v) {
    		$_POST[$k] = $_GET[$k];
    	}
    }
    
    ?>
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="utf-8">
    <title>管理人へメールを送る</title>
    
    <link type="text/css" rel="stylesheet" href="adminmail.css">
    
    </head>
    <body>
    
    <div id="header" style="text-align:left;">
    	<a href="adminmail_1.php">リロード</a>
    </div>
    
    <div id="container">
    	
    	<div id="top">
    	  <h1>管理人へメールを送る</h1>
    	</div>
    	<div id="message">
    		<?= $message ?>
    	</div>	
    
    	<div id="content">
    		<fieldset>
    			<legend>送信情報</legend>
    			
    			<div class="explain">
    				<ol>
    						<li>下記のフォームを埋めて投稿してください。</li>
    						<li>メールアドレスは正しく入力してください。</li>
    					</ol>
    				<p></p>
    			</div>
    
    
    			<form action="adminmail_2.php" method="post" class="form">
    				
    				<p><label for="subject">件名</label></p>
    				
    				<p><input type="text" name="subject" value="<?= $_POST["subject"] ?>" id="subject" size="60"></p>
    				
    				<p><label for="usermail">メールアドレス</label></p>
    				
    				<p><input type="text" name="usermail" value="<?= $_POST["usermail"] ?>" id="usermail" size="60"></p>
    				
    				<p><label for="body">本文</label></p>
    				
    				<p><textarea cols="50" rows="5" name="body" id="body"><?= $_POST["body"] ?></textarea></p>
    				
    				<input type="submit" name="confirm" value="確認" class="buttons">
    				
    			</form>
    		</fieldset>
    	</div>
    	
    	<div class="clear"></div>
    	
    </div>
    
    
    </body>
    </html>
    
    
    
    adminmail_2.php
    
    メールアドレスのフォーマットチェックには、filter_var 関数(PHP 5 >= 5.2.0) を使用しています。
    
    <?php
    require_once( "common.php" );
    
    $err = false;
    $param = "";
    
    // 入力チェック
    if( trim( $_POST['subject'] ) == "") {
    	$err = true;
    	if ( $param != "" ) {
    		$param .= "&";
    	}
    	$param .= "e1=1";
    }
    if( trim( $_POST['usermail'] ) == "") {
    	$err = true;
    	if ( $param != "" ) {
    		$param .= "&";
    	}
    	$param .= "e2=1";
    }
    else {
    	if( !filter_var($_POST['usermail'], FILTER_VALIDATE_EMAIL)) {
    		$err = true;
    		if ( $param != "" ) {
    			$param .= "&";
    		}
    		$param .= "e2=2";
    	}
    }
    if( trim( $_POST['body'] ) == "") {
    	$err = true;
    	if ( $param != "" ) {
    		$param .= "&";
    	}
    	$param .= "e3=1";
    }
    
    if ( $err ) {
    	$url = "adminmail_1.php?{$param}";
    	$url .= "&subject=" . urlencode($_POST['subject']);
    	$url .= "&usermail=" . $_POST['usermail'];
    	$url .= "&body=" . urlencode($_POST['body']);
    	header("Location: {$url}");
    	exit();
    }
    
    foreach($_POST as $k => $v) {
    	$v = str_replace("\"","&#34;",$v);
    	$v = str_replace("<","&lt;",$v);
    	$_POST[$k] = str_replace(">","&gt;",$v);
    }
    
    $_POST["body_html"] = str_replace("\r\n","<br>",$_POST["body"]);
    $_POST["body_html"] = str_replace("\n","<br>",$_POST["body_html"]);
    
    
    ?>
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="utf-8">
    <title>管理人へメールを送る</title>
    
    <link type="text/css" rel="stylesheet" href="adminmail.css">
    
    </head>
    <body>
    
    <div id="header" style="text-align:left;">
    	<a href="adminmail_1.php">リロード</a>
    </div>
    
    <div id="container">
    	
    	<div id="top">
    	  <h1>管理人へメールを送る</h1>
    	</div>
    	
    		
    	<div id="content">
    		<fieldset>
    			<legend>送信情報</legend>
    			
    			<div class="explain">
    				<ol>
    						<li>下記のフォームを埋めて投稿してください。</li>
    						<li>メールアドレスは正しく入力してください。</li>
    					</ol>
    				<p></p>
    			</div>
    			
    			
    			<form action="adminmail_3.php" method="post" class="form">
    				<p><label>件名</label></p>
    				
    				<p><?= $_POST["subject"] ?></p>
    				<input type="hidden" name="subject" value="<?= $_POST["subject"] ?>">
    				<p><label>メールアドレス</label></p>
    				
    				<p><?= $_POST["usermail"] ?></p>
    				<input type="hidden" name="usermail" value="<?= $_POST["usermail"] ?>">
    				<p><label>本文</label></p>
    				
    				<p><?= $_POST["body_html"] ?></p>
    				<input type="hidden" name="body" value="<?= $_POST["body"] ?>">
    				<input type="submit" name="edit" value="<< 修正" class="buttons" formaction="adminmail_1.php">
    				<input type="submit" name="sendmail" value="送信" class="buttons">
    			</form>
    		</fieldset>
    	</div>
    	
    	<div class="clear"></div>
    	
    </div>
    
    
    </body>
    </html>
    
    
    
    adminmail_3.php
    
    ここでメール送信を実行しています。送信後、この画面にリダイレクトしているので、ブラウザで再表示しても再度送信しようとする事はありません。
    
    <?php
    require_once( "common.php" );
    
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
    
    	admin_mail( $_POST["body"], $_POST["usermail"], $_POST["subject"]);
    
    	header("Location: adminmail_3.php");
    	exit();
    
    }
    
    ?>
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="utf-8">
    <title>管理人へメールを送る</title>
    
    <link type="text/css" rel="stylesheet" href="adminmail.css">
    
    </head>
    <body>
    
    <div id="header" style="text-align:left;">
    	<a href="adminmail_1.php">リロード</a>
    </div>
    
    <div id="container">
    	
    	<div id="top">
    	  <h1>管理人へメールを送る</h1>
    	</div>
    	
    		
    	<div id="content">
    		<fieldset>
    			<legend>送信情報</legend>
    			
    			<div class="explain">
    				<ol>
    						<li>下記のフォームを埋めて投稿してください。</li>
    						<li>メールアドレスは正しく入力してください。</li>
    					</ol>
    				<p></p>
    			</div>
    			
    			
    					<p style="color:#336699; font-weight:bold;">メールを送信しました。</p>
    			<p><a href="adminmail_1.php">メール作成フォームへ戻る</a></p>
    					<div class="clear"></div>
    		</fieldset>
    	</div>
    	
    	<div class="clear"></div>
    	
    </div>
    
    
    </body>
    </html>
    
    
    送り先が固定なのでここでは実装していませんが、セッションを使えば最初の画面表示から、メール送信までの時間間隔が一定以上必要になるようにする事ができます。
    
    
    
    posted by lightbox at 2015-05-15 07:44 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2014年08月01日


    PHP : リモートのファイルサイズを取得する

    PHP のオンラインマニュアルの投稿データにあります。( CTRL+F で Here's the best way をサーチ )
    
    <?php
    $remoteFile = '対象 URL(http)';
    $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);
    $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];
    }
    
    echo 'HTTP Status: ' . $status . "\n";
    echo 'Content-Length: ' . $contentLength;
    ?>
    
    Here's the best way (that I've found) to get the size of a remote file
    
    なんて書いてあるのですが、確かにうまくいきます。当たり前と言えばあたりまえですが、An HTTPD でログを取るとこんな感じです。
    <<< s=300: Fri Sep 18 23:30:20 2009 <<<
    HEAD /php/elenat.ttf HTTP/1.1
    Host: localhost
    Accept: */*
    
    >>> s=300: Fri Sep 18 23:30:20 2009 >>>
    HTTP/1.1 200 Document follows
    MIME-Version: 1.0
    Server: AnWeb/1.42p
    Date: Fri, 18 Sep 2009 14:30:20 GMT
    Content-Type: application/octet-stream
    Accept-Ranges: bytes
    Content-Length: 5116536
    ETag: "43a96df0-4e1278"
    Last-Modified: Wed, 21 Dec 2005 15:00:00 GMT
    
    レスポンスはすぐに返ってきます。実際使う場合は、curl が使えるか事前にチェックする必要がありますが、たぶん大丈夫でしょう。ですが、Windows の場合は意図的に使えるようにする必要があります(php.ini でextension=php_curl.dll)。こちらは、実際にそのへんを考慮して作ったサンプルです
    posted by lightbox at 2014-08-01 12:17 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    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);
    
    }
    // **************************************************
    // コマンドライン
    // **************************************************
    else {
    	$ihandle = fopen($remoteFile, "r");
    	$ohandle = fopen($fileName, "w");
    	if ( $ihandle ) {
    
    		while( TRUE ) {
    			if ( feof( $ihandle ) ) {
    				break;
    			}
    			$ret = fread( $ihandle, 1024 );
    			fwrite( $ohandle,  $ret );
    		}
    
    		fclose( $ohandle );
    		fclose( $ihandle );
    	}
    }
    
    ?>
    
    
    
    
    関連する記事
    
    
    
    
    posted by lightbox at 2014-08-01 12:09 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする

    2014年07月31日


    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 = 'winofsql.jp/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($curl);
    }
    
    // ************************************
    // 終了
    // ************************************
    curl_close($ch);
    
    // ************************************
    // 後処理
    // ************************************
    fclose($fp);
    fclose($fpe);
    
    print $result . "\n";
    ?>
    OK
    
    
    
    
    
    タグ:PHP Curl 通信
    posted by lightbox at 2014-07-31 14:14 | PHP + 通信 | このブログの読者になる | 更新情報をチェックする
    Seesaa の各ページの表示について
    Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。
    
    Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。
    
    また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。
    
    ※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです
    
    対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。
    
    
    ※ エキスパートモードで表示しています
    
    アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります
    
    
    <% if:page_name eq 'archive' -%>
    アーカイブページでのみ表示される内容
    <% /if %>
    
    <% if:page_name eq 'category' -%>
    カテゴリページでのみ表示される内容
    <% /if %>
    
    <% if:page_name eq 'tag' -%>
    タグページでのみ表示される内容
    <% /if %>
    
    この記述は、以下の場所で使用します


    Windows
    container 終わり

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

    Android SDK ポケットリファレンス
    改訂版 Webデザイナーのための jQuery入門
    今すぐ使えるかんたん ホームページ HTML&CSS入門
    CSS ドロップシャドウの参考デモ
    Google Hosted Libraries
    cdnjs
    BUTTONS (CSS でボタン)
    イラストAC
    ぱくたそ
    写真素材 足成
    フリーフォント一覧
    utf8 文字ツール
    右サイド 終わり
    base 終わり