LoginSignup
18
19

More than 5 years have passed since last update.

Guzzleでファイルアップロードする

Last updated at Posted at 2016-02-11

前々から少し気になっていたGuzzleでファイルアップロード(multipart/form-dataを送信)する方法を調べてみました。

まあ、ここを見れば済む話ですが。

ファイルの受け取り側

とりあえず、下記のようなファイルアップロードを受けるAPIを用意してみた。
いろいろ書いているが、そんなに複雑なことはしていない(テストなのでエラー処理も最低限)。

エラーはまず$_FILES['file']['error']を利用して考える方がいいです。

multipartをチェックしたいので、とりあえず、access_keyとfileを受け取るようにしている。

receive.php

<?php

    $response   = [];
    $access_key = "";
    $remote_size = 0;

    //access_key
    if(isset($_POST['access_key'])) $access_key = htmlspecialchars($_POST['access_key']);

    //access_key error
    if($access_key != "hoge")
    {
        $response['status'] = "NG";
        $response['msg'] = "error";
        $response['size'] = 0;

        header('Content-type: application/json');
        echo json_encode($response);
        exit;
    }


    //一時ファイルが存在するか?
    //アップロードされたファイルは一時ファイルとして保存される。
    if(is_uploaded_file($_FILES['file']['tmp_name']))
    {
        $remote_size = $_FILES['file']['size'];
        $response['size'] = $remote_size;

        //size check
        if($remote_size > 1000 * 1024)
        {
            $response['status'] = "NG";
            $response['msg'] = "file size error";

            header('Content-type: application/json');
            echo json_encode($response);
            exit;
        }

        //一時ファイルを正式ファイルにコピー
        //moveすると、一時ファイルは削除される
        if(move_uploaded_file($_FILES['file']['tmp_name'], "./".$_FILES['file']['name']))
        {
            //正常
            $response['status'] = "OK";
            $response['msg'] = "file uploaded";

        }else{

            //moveエラー
            $response['status'] = "NG";
            $response['msg'] = "error when saving";

        }
    }else{

        //uploadエラー
        $response['status'] = "NG";
        $response['msg'] = "file not uploaded";
        $response['size'] = 0;

    }

    header('Content-type: application/json');
    echo json_encode($response);

ファイルの送信側

まず、Guzzleのインストールは、必要なディレクトリで、

composer require guzzlehttp/guzzle

とします。

guzzleにおいては、multipartの場合、送信する値を、

[
    'name' => 'access_key',
    'contents' => 'hoge',
]

の様に、nameとcontentsに分けて設定するのがポイントです。

普通のgetやpostの時のように、'access_key => 'hoge'の様にしない。

また、fileの指定は、

[
    'name' => 'file',
    'contents' => fopen('file/path','r'),
]

という感じでfopenで指定する。高水準にいきなり低水準が出てきます。
とは言え、慣れればどうってことはありません。

<?php

    require_once 'vendor/autoload.php';

    //get filesize
    $local_size = filesize('hoge.jpg');

    //upload
    $client = new GuzzleHttp\Client();

    $response = $client->request('POST','http://localhost/receive.php',[
        'multipart' => [
            [
                'name' => 'access_key',
                'contents' => 'hoge',
            ],
            [
                'name' => 'file',
                'contents' => fopen('hoge.jpg','r'),
            ],
        ]
    ]);

    //get response(josn -> obje)
    $obj = json_decode($response->getBody());

    $status = $obj->status;
    $msg = $obj->msg;
    $size = $obj->size;

    echo "status=".$status."<br>";
    echo "msg=".$msg."<br>";
    echo "remote file size=".$size."<br>";
    echo "local file size=".$local_size."<br>";

ここでは、レスポンスはjsonなので、decodeして、各要素を取得しています。
まともにアップロードされたら、

status=OK
msg=file uploaded
remote file size=806959
local file size=806959

という感じで表示されます。
size取得して、アップロードチェックしても良いかもしれません。

18
19
0

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
18
19