PHPから直接file_get_contentsでファイルをPOSTしたいときのやり方

#概要
外部サービスAPIとかでPHPから直接ファイルを送りたいときの処理です。
※サンプルコードなのでエラー処理は甘めになっています。実案件で使うときは気を付けてください。


#受信者側(相手)
 FILESとPOSTのデータを表示(+ファイル保存)するだけのシンプルな画面です。

```php: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>
```
![1_黒やぎさんサイト(直アクセス).png](https://qiita-image-store.s3.amazonaws.com/0/66209/80e47e60-5605-5025-3807-dcdfff3bea69.png)




#送信者側(自分)
前述の画面にPHPから直接ファイル付きでPOST送信を行う画面です。

```php: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で取得した
　相手側のコンテンツが出力されています。
![2_画像ファイルのバイナリデータ-のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/66209/bacd9241-7649-34d6-b67e-4cc098442805.png)

## 実行結果(相手のサーバー)
※実行するたびにファイルがたまっていきます。
![3_ファイルも書き出されます.png](https://qiita-image-store.s3.amazonaws.com/0/66209/93a84b4b-3a9d-1a02-3415-52facc89f172.png)




#所感
HTML上のフォームから送るのは結構簡単だけど、PHPから直接って結構めんどくさい。
boundary(バインダリー)の入れ方間違えると値が欠けてしまったりして結構ハマりました。