Web・IT うんたらら

業務系とWeb系の狭間でIT業界を彷徨いながら備忘録と足跡を残していきます

PHPで HTTP POST送信 (multipartでファイルアップロード対応)

2013.03.04 追記

※PHP4系にも対応したコードも書きました。以下のURLからどうぞ

http://vamview.hatenablog.com/entry/2013/03/04/221309

 

 

さてさて今回、殆ど初めて触るPHPにて、サーバにあるファイルをPostで送信する処理が必要になりました。

PEAR::HTTP_Request というライブラリを利用すると簡単に実装できそうですが、諸事情により、今回は標準でないライブラリの使用ができません。

ということで、file_get_contents()を応用した関数を書いてみました。

ファイルアップロードが要らない場合は普通のPOSTとしても動作するよう統一化してます。

 

※注 PHPは普段使わないのでウンコードの可能性アリ。親切な方添削お願いします。



define('CRLF', "\r\n");

 

//$urlに、$paramsのパラメータをpost

function httpPost($url, $params, $files = []){

    $isMultipart = (count($files)) ? true : false;

    if ($isMultipart){

        //ファイルアップロードを伴う場合、multipartで送信

        $boundary = '---------------------------'.time();

        $contentType = "Content-Type: multipart/form-data; boundary=" . $boundary;

        $data = '';

        foreach($params as $key => $value) {

            $data .= "--$boundary" . CRLF;

            $data .= 'Content-Disposition: form-data; name=' . $key . CRLF . CRLF;

            $data .= $value . CRLF;

        }

        foreach($files as $key => $file) {

            $data .= "--$boundary" . CRLF;

            $data .= sprintf('Content-Disposition: form-data; name="%s"; filename="%s"%s', 'UploadFile', basename($file), CRLF);

            $data .= 'Content-Type: application/octet-stream'. CRLF;

            $data .= file_get_contents($file) . CRLF;

        }

        $data .= "--$boundary--" . CRLF;

    } else {

        //パラメータのみを送信

        $contentType = 'Content-Type: application/x-www-form-urlencoded';

        $data = http_build_query($params);

    }

    $headers = array(

        $contentType,

        'Content-Length: '.strlen($data)

    );

    $options = array('http' => array(

        'method'  => 'POST',

        'content' => $data,

        'header'  => implode(CRLF, $headers)

    ));

    $contents = file_get_contents($url, false, stream_context_create($options));

    return $contents;

}

 

//呼び出し方はこんな感じ

$file = 'D:\tmp\test.txt';    //アップロードするテキストファイル 

$files = array(

    'UploadFile' => $file

);

$params = array(

    'title' => 'test',

    'hoge' => 'fuga'

);

$url = 'http://www.xxxxxxx.example.com/api';

$response = httpPost($url, $params, $files);

 



さて、余談ですがmultipartというと、先輩諸氏のサンプルではよくヘッダに以下の行を追加してあります。

 

Content-Transfer-Encoding: binary

 

が、どうもこれはMIMEの規定らしく、HTTPではいらないんじゃないかなと思い、今回は除外したんですがどうなんでしょう。
ブラウザから input type="file"をsubmitした際もこのヘッダはついていないようなのですが……。