前々から少し気になっていた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取得して、アップロードチェックしても良いかもしれません。