LoginSignup
12
14

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-06-06

概要

外部サービス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>

1_黒やぎさんサイト(直アクセス).png

送信者側(自分)

前述の画面に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で取得した
 相手側のコンテンツが出力されています。
2_画像ファイルのバイナリデータ-のコピー.png

実行結果(相手のサーバー)

※実行するたびにファイルがたまっていきます。
3_ファイルも書き出されます.png

所感

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

12
14
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14