概要
外部サービスAPIとかでPHPから直接ファイルを送りたいときの処理です。
※サンプルコードなのでエラー処理は甘めになっています。実案件で使うときは気を付けてください。
受信者側(相手)
FILESとPOSTのデータを表示(+ファイル保存)するだけのシンプルな画面です。
kuroyagi/postDataSandbox.php
<!doctype html>
<html style="height:100%;">
<head>
<meta charset="utf-8">
<title>POST SANDBOX</title>
</head>
<body style="">
<h2>$_FILES</h2>
<?php
$now = new DateTime();
$fileSavePath = dirname(__FILE__).'/post_'.$now->format('YmdHis');
if(!file_exists($fileSavePath)){
mkdir($fileSavePath);
}
if(count($_FILES) > 0){
foreach($_FILES as $file) { ?>
<hr />
ファイルの情報<br>
<textarea style="min-width:300px;height:120px;"><?php var_dump($file);?></textarea>
<br>
ファイルの中身<br>
<textarea style="min-width:300px;height:120px;"><?php echo file_get_contents($file['tmp_name']);?></textarea>
<?php
//受け取ったファイルを移動する
if($file['error'] == UPLOAD_ERR_OK){
move_uploaded_file($file['tmp_name'], $fileSavePath.'/'.$file['name']);
}
}
} else { ?>
※ファイル添付はありません
<?php
}
?>
<hr />
<h2>$_POST</h2>
<textarea style="min-width:300px;height:120px;display:block">
<?php var_dump($_POST);?>
</textarea>
</body>
</html>
送信者側(自分)
前述の画面にPHPから直接ファイル付きでPOST送信を行う画面です。
shiroyagi/postDataSender.php
<!doctype html>
<html style="height:100%;">
<head>
<meta charset="utf-8">
<title>POST SENDER</title>
</head>
<body >
<?php
function sendData(){
$CNL = "\r\n";//改行を変数化
//POST送信先URL
$sendUrl = 'http://example.com/*******/kuroyagi/postDataSandbox.php';
//テキストデータを記述
$arrPost = array(
'from' => '白やぎ'
,'to' => '黒やぎさん'
,'subject' => '今日のお手紙'
,'mailbody' => 'お元気ですか?'
);
//画像ファイルパスを記述
$filePath = 'photo.jpg';
$arrContent = [];
$boundary = "----1234567890";
//ペイロード作成
$arrContent[] = $CNL.'--'.$boundary;//開始
if(count($arrPost) > 0){
foreach($arrPost as $key => $val) {
$arrContent[] = 'Content-Disposition: form-data; name="'.$key.'"'.$CNL;
$arrContent[] = $val;
$arrContent[] = '--'.$boundary;
}
}
if(file_exists($filePath)){
$imageFile = file_get_contents($filePath);
$key = 'file';
$arrContent[] = 'Content-Disposition: form-data; name="'.$key.'"; filename="'.basename($filePath).'"';
$arrContent[] = 'Content-Type: image/jpeg';
$arrContent[] = $CNL.$imageFile;//画像ファイルデータを挿入
$arrContent[] = '--'.$boundary;
}
$content = join($CNL, $arrContent);
$content .= '--'.$CNL;//終端
$header = join($CNL,array(
"Content-Type: multipart/form-data; boundary=".$boundary,
"Content-Length: ".strlen($content)
));
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => $header,
'content' => $content
)
));
//ストリームラッパコンテキスト内容を出力(動作確認用)
echo '<textarea>';
var_dump(stream_context_get_options($context));
echo '</textarea>';
//送信
$result = file_get_contents($sendUrl, false, $context);
if($result !== false){
echo $result;//送信先の結果を出力
} else {
echo '送信失敗';
}
}
?>
<h2>送信結果</h2>
<?php sendData();?>
</body>
</html>
実行結果(自分)
※一番上のテキストボックスの下はfile_get_contentsで取得した
相手側のコンテンツが出力されています。
実行結果(相手のサーバー)
所感
HTML上のフォームから送るのは結構簡単だけど、PHPから直接って結構めんどくさい。
boundary(バインダリー)の入れ方間違えると値が欠けてしまったりして結構ハマりました。