新規投稿
フォローする

phpによるファイルアップロード

初歩的なことだと思うのですが、phpで外部サイトからファイルをアップロードするプログラムを作りたいのですが、kintoneのrest apiを見てもイメージがつかめず困っています。
どのようにリクエストヘッダを書き、どのようにレスポンスが返ってくるのでしょうか?

0

15件のコメント

Avatar
Ryu Yamashita

後藤正樹さん

ファイルの取扱については、multipart/form-data について多少理解が必要ですが、これを掴んでいくには
POSTMANやcRULコマンドで試すところから
入るのは個人的にお勧めです。file.jsonに限ったことではありませんが、POSTMANでリクエストする際にこちらにあるようにChromeのNetworkパネルでリクエストの中身を見てみるのも有効だと思います。

どのようにリクエストヘッダを書き、どのようにレスポンスが返ってくるのでしょうか?

リファレンスの通りになってしまいますが、multipartと言うだけあって、boundaryと呼ばれるもので区切りながらファイルの中身を間に入れていきます。
レスポンスとしては、fileKeyと呼ばれる値がJSONで返ってきます。

PHPであれば、

$fileName = mb_convert_encoding(mb_substr($filePath, mb_strrpos($filePath, DIRECTORY_SEPARATOR) + 1), "UTF-8", "auto");
$finfo = finfo_open(FILEINFO_MIME_TYPE);  
$mimeType = finfo_file($finfo, $filePath);  
finfo_close($finfo);  
$fileArray = array ("file" => "@$filePath;filename=$fileName;type=$mimeType");
$kintoneUrl = ($spaceId == '') ? ("https://".$subDomain.".cybozu.com/k/v1/file.json") : ("https://".$subDomain.".cybozu.com/k/guest/".$spaceId."/v1/file.json");
$authToken = base64_encode($id.":".$passWord);
$basicAuthToken = base64_encode($basicId.":".$basicPassWord);
$header = array("X-Cybozu-Authorization: $authToken", "Authorization: basic $basicAuthToken");

といった感じで、あとはリクエストヘッダ($header)、リクエストボディ($fileArray)、リクエストURL($kintoneUrl)をセットしてPOSTすれば大丈夫だと思います。

また、Excel VBAの例ですが、こちらも見比べることで参考になると思います。

いかがでしょうか?

1
Avatar
後藤正樹

Ryu Yamashitaさん

回答ありがとうございます。
いろいろ自分で試行錯誤しているのですが、どうもうまくいきません。
あと、もう少しだと思うのですが
status: 520 cybozu error: CB_IL02 body: {"message":"不正なリクエストです。","id":"1505999166-2079130251","code":"CB_IL02"}

というエラーが起きてしまいます。

コードは以下のとおりです。

require_once("/HTTP/Request2.php");

$subDomain = "sabDomain";
$id = "loginName";
$passWord = "passWord";
$filePath = "C:/Users/m.goto/Desktop/fileupload/upload/report.php";
$appId = 121;


$fileName = mb_convert_encoding(mb_substr($filePath, mb_strrpos($filePath, DIRECTORY_SEPARATOR) + 1), "UTF-8", "auto");
//$fileName = "report.php";
$finfo = finfo_open(FILEINFO_MIME_TYPE);  
$mimeType = finfo_file($finfo, $filePath);  
finfo_close($finfo);  
$fileArray = array ("file" => "$filePath;filename=$fileName;type=$mimeType");
$kintoneUrl = "https://".$subDomain.".cybozu.com/k/v1/file.json";
$authToken = base64_encode($id.":".$passWord);
$basicAuthToken = base64_encode($id.":".$passWord);

$header = array("X-Cybozu-Authorization:". "$authToken", 
    "Host: " . $subDomain . ".cybozu.com:443",
    "Authorization: " . "basic $basicAuthToken"
);

try {

$request = new HTTP_Request2();
$request->setMethod(HTTP_Request2::METHOD_POST);

$request->setHeader($header);
$request->setUrl($kintoneUrl);
$request->setBody(json_encode($fileArray));

$request->setConfig(array(
  'ssl_verify_host' => false,
  'ssl_verify_peer' => false
));

// レスポンス取得
$response = $request->send();

// HTTP_Request2のエラーを表示
} catch (HTTP_Request2_Exception $e) {
die($e->getMessage());
// それ以外のエラーを表示
} catch (Exception $e) {
die($e->getMessage());
}

// エラー時
if ($response->getStatus() != "200") {
echo sprintf("status: %s\n", $response->getStatus());
echo sprintf("cybozu error: %s\n", $response->getHeader('x-cybozu-error'));
echo sprintf("body: \n%s\n", $response->getBody());
die;
}

リクエストの記述方法などが間違っているのでしょうか?

0
Avatar
後藤正樹

自力で解決できました。
リクエストの仕方がぜんぜん違いました。
setBodyでリクエストボディを設定するのではなく、addUpLoad関数を使ったらうまくいきました。

0
Avatar
Ryu Yamashita

> 自力で解決できました。

良かったです!

自力で解決できました。

反応遅れて申し訳ないですが、良かったです^^

$request->setBody(json_encode($fileArray));

少し補足ですが、こちらはfile.jsonというURLですが、ファイルについてはリクエストボディはJSON形式ではありません(Content-Type: application/jsonではない)ので、
json_encodeという訳にもいかないんですよね。

0
Avatar
az

I'm trying to upload file to kintone using php. Can you help me?

0
Avatar
Ryu Yamashita

az bz

Aren't our previous snippets helpful for you?

0
Avatar
az

I'm trying to upload file to kintone that will response a file key.

 

0
Avatar
Ryu Yamashita

The fileKey you obtained is required to attach to kintone record like this. https://developer.kintone.io/hc/en-us/articles/212494448/ Make sense?

0
Avatar
az

Yes, I want to return the file key (like this  "fileKey": "c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6") if I upload files from an external site with php. It is possible?

0
Avatar
shigeyoshi tsujiuchi

setBodyでリクエストボディを設定するのではなく、addUpLoad関数を使ったらうまくいきました。

というコメントがありますが、

実際どのようなコードを書けば実現できるのでしょうか?

サンプルコードを教えて頂きたいです。

 

よろしくお願いします。

0
Avatar
瀧ヶ平

shigeyoshi tsujiuchiさん
cstapの瀧ヶ平です。

$request->setBody(json_encode($fileArray));

とある部分を

$request->addUpload($fileName, $filePath, $fileName, $mimeType);

のようにすれば良いのではないでしょうか?
(当方確認とっていないのでわかりませんが…)

0
Avatar
Ryu Yamashita

ファイルをアップロードしてレコードに紐つけるという一連の流れをcURLを使ってゆるっと関数化したものが手元にあったので、共有します。今ならパスワード認証じゃなくてAPIトークン使う方がいいですが。

 

I found a simple snippet that allows a file to upload and attach to a record using cURL, so sharing it. It is better to replace user authentication with API token.

 

  function fileUploadToKintone($url, $fieldCode, $recordNum, $appId, $spaceId, $subDomain, $id, $passWord, $basicId, $basicPassWord){
    // prepare to upload file
    $fileName = mb_convert_encoding(mb_substr($url, mb_strrpos($url, DIRECTORY_SEPARATOR) + 1), "UTF-8", "auto");
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $url);
    finfo_close($finfo);

 

    $fileArray = array ("file" => "@$url;filename=$fileName;type=$mimeType");
    $kintoneUrl = ($spaceId == '') ? ("https://".$subDomain.".cybozu.com/k/v1/file.json") : ("https://".$subDomain.".cybozu.com/k/guest/".$spaceId."/v1/file.json");
    $authToken = base64_encode($id.":".$passWord);
    $basicAuthToken = base64_encode($basicId.":".$basicPassWord);
    $header = array("X-Cybozu-Authorization: $authToken", "Authorization: basic $basicAuthToken");
    // send request to upload
    $response = $this->requestHttp('POST', $kintoneUrl, $header, $fileArray);
    // obtain fileKey
    $responseObject = json_decode($response);
    $fileKey = $responseObject->fileKey;
    $recordObject = new stdClass;
    // prepare to attach file to kintone record
    $fileObject = new stdClass;
    $fileObject->fileKey = $fileKey;
    $fileObjectArray = array($fileObject);
    $attachedFileObject = new stdClass;
    $attachedFileObject->value = $fileObjectArray;

 

    $recordObject->$fieldCode = $attachedFileObject;
    $requestObject = new stdClass;
    $requestObject->app = $appId;
    $requestObject->id = $recordNum;
    $requestObject->record = $recordObject;
    $requestJson = json_encode($requestObject);
    $kintoneUrl = ($spaceId == '') ? ("https://".$subDomain.".cybozu.com/k/v1/record.json") : ("https://".$subDomain.".cybozu.com/k/guest/".$spaceId."/v1/record.json");
    $header = array("X-Cybozu-Authorization: $authToken", "Authorization: basic $basicAuthToken", "Content-Type: application/json");
    // send request to update record
    $response = $this->requestHttp('PUT', $kintoneUrl, $header, $requestJson);
    return($response);
  }

 

 
0
Avatar
izuhara

上記のコードに従い、以下のようにソースを書いたのですが、

Status=520でエラーが「CB_IL02」

になってしまいます。

なお、「HTTP_Request2を利用したkintone REST APIの扱い方」

https://developer.cybozu.io/hc/ja/articles/202657614-HTTP-Request2%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9Fkintone-REST-API%E3%81%AE%E6%89%B1%E3%81%84%E6%96%B9

ではうまく動作しているので、addUpLoad()の箇所がおかしいのだと思うのですが、特定できず。

ご教示ください。

 

try {

require "HTTP/Request2.php";

$kintone_url = "https://○○○.cybozu.com/k/v1/file.json";
$fileName = mb_convert_encoding(mb_substr($filePath, mb_strrpos($filePath, DIRECTORY_SEPARATOR) + 1), "UTF-8", "auto");
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);

$req = new Http_Request2();
$req->setHeader($header);
$req->setUrl($kintone_url);
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addUpLoad('personal_docs', $filePath, $fileName, $mimeType);
$response = $req->send()->getBody();

} catch (HTTP_Request2_Exception $e) {
die($e->getMessage());
// それ以外のエラーを表示
} catch (Exception $e) {
die($e->getMessage());
}

0
Avatar
izuhara

同様にcurlでも試しましたがうまくいかず・・・

コンソールからcurlで直接たたいた場合は成功しています

$header = array(
"X-Cybozu-API-Token:" . $kintone_client_api_key,
);

$fileName = mb_convert_encoding(mb_substr($filePath, mb_strrpos($filePath, DIRECTORY_SEPARATOR) + 1), "UTF-8", "auto");
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);

$data = array(
'file' => '@' . $filePath . ";filename=" . $fileName . ";type=" . $mimeType
);

$curl = curl_init("https://○○○.cybozu.com/k/v1/file.json");
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

$res = curl_exec($curl);

izuharaにより編集されました
0
Avatar
izuhara

すいません、自己解決しました。

postの形式が誤っていたようです。

以下、うまくいったパターンです。

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://○○○.cybozu.com/k/v1/file.json",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\n".
"Content-Disposition: form-data; name=\"file\"; filename=\"$fileName\"\r\n".
"Content-Type: text/plain"."\r\n\r\n".
file_get_contents($filePath) . "\r\n" .
"------WebKitFormBoundary7MA4YWxkTrZu0gW--",
CURLOPT_HTTPHEADER => array(
"X-Cybozu-API-Token: ○○○",
"content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
),
));

1
サインインしてコメントを残してください。