PHP中用CURL向PandaDoc API发送Base64文件及JSON遇错求助
问题描述
我尝试通过PandaDoc的「从文件创建文档」API,使用PHP的CURL发送文件,同时需在multipart/form-data中包含含收件人等信息的JSON数据。但我无法正确配置该调用,持续收到API返回的错误信息(如“There is field called file”)。以下是我的现有代码:
public function createDocument() { $p = getmypid(); $m = "({$p}): PandaDoc::create document: "; $postfields = array(); $postfields['name'] = $this->document->name; $postfields['file'] = $this->document->file; //base 64 encoded PDF $recipients = array( array( 'email' => 'a.mcdoogle@test.com', 'first_name' => 'Andrew', 'last_name' => 'Mcdoogle', 'role' => 'user', 'signing_order' => 1 ) ); $data = array(); $data['recipients'] = $recipients; $owner = array( "email" => "john@example.com" ); $data['owner'] = $owner; $postfields['data'] = json_encode($data); $header = array("Authorization: API-Key {$this->api_key}", "Content-Type: multipart/form-data", "accept" => "application/json"); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); $res = curl_exec($ch); if ($res === false) { $errno = curl_errno($ch); $error = curl_error($ch); error_log("{$m}cURL error: {$error} ({$errno})"); throw new Exception("{$m}cURL error: {$error} ({$errno})"); } $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close ($ch); error_log("{$m}Results from PandaDoc: {$res}"); $response = json_decode($res); return $response; }
请问我哪里出错了?
问题分析与修复方案
你的代码存在三个关键问题:
文件字段格式错误
PandaDoc的multipart/form-data请求中,file字段需要传递原始文件二进制内容或文件资源句柄,而非Base64编码字符串。你需要将Base64编码的内容解码为原始二进制数据。手动指定
Content-Type导致解析失败
PHP CURL发送multipart/form-data请求时,会自动生成包含边界标识的正确Content-Type头。手动设置该头会覆盖自动生成的内容,导致API无法正确识别表单字段。SSL验证被关闭(非直接错误但有安全风险)
代码中关闭了SSL证书验证,这会带来安全隐患,建议恢复默认验证逻辑。
修正后的代码
public function createDocument() { $p = getmypid(); $m = "({$p}): PandaDoc::create document: "; $postfields = array(); $postfields['name'] = $this->document->name; // 将Base64编码的PDF解码为原始二进制数据 $postfields['file'] = base64_decode($this->document->file); $recipients = array( array( 'email' => 'a.mcdoogle@test.com', 'first_name' => 'Andrew', 'last_name' => 'Mcdoogle', 'role' => 'user', 'signing_order' => 1 ) ); $data = array( 'recipients' => $recipients, 'owner' => array("email" => "john@example.com") ); $postfields['data'] = json_encode($data); // 移除手动设置的Content-Type,保留授权和Accept头 $header = array( "Authorization: API-Key {$this->api_key}", "accept: application/json" ); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 恢复SSL验证,提升安全性 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); $res = curl_exec($ch); if ($res === false) { $errno = curl_errno($ch); $error = curl_error($ch); error_log("{$m}cURL error: {$error} ({$errno})"); throw new Exception("{$m}cURL error: {$error} ({$errno})"); } $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close ($ch); error_log("{$m}Results from PandaDoc: {$res}"); $response = json_decode($res); return $response; }
额外优化建议
如果你的$this->document->file是本地文件路径而非Base64字符串,推荐使用CURLFile类传递文件,这是PHP处理表单文件上传的标准方式:
$postfields['file'] = new CURLFile($this->document->file);
内容的提问来源于stack exchange,提问作者user794846
相关产品推荐
相关产品推荐

