【问题标题】:How do I post to a Google script with cURL in PHP and return text?如何在 PHP 中使用 cURL 发布到 Google 脚本并返回文本?
【发布时间】:2018-05-02 12:55:13
【问题描述】:

我正在尝试做最低限度的工作,只是为了让它发挥作用。

这是我的 Google 脚本:

function doPost(e) {
  return ContentService.createTextOutput(JSON.stringify(e.parameter));
}

这是我的 PHP 代码:

$url = 'https://script.google.com/a/somedomain.com/macros/s/### script id ###/exec';
$data['name'] = "Joe";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch);
$error  = curl_error($ch);

执行这个,$resulttrue

如果我取消注释 CURLOPT_RETURNTRANSFER 行,$result =

<HTML>
<HEAD>
<TITLE>Bad Request</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Bad Request</H1>
<H2>Error 400</H2>
</BODY>
</HTML>

$error 始终为空。

我会使用doGet(),但我需要发送一些相当大的 POST,这将超出 GET 的处理能力。

如何发布到 Google 脚本并返回数据?

----- 更新 ------

我刚刚得知我的首席开发人员前段时间尝试过此操作,并在返回时得出了 doPost() 错误,因此显然不仅仅是我。我的看法是,谷歌根本不够可靠,无法使用。我希望有人能证明我错了。

----- 更新 2 - 修复 ---------

显然这是问题所在:

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

需要:

curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

不知道为什么http_build_query() 导致它出错。

【问题讨论】:

  • 我猜curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data")); 是罪魁祸首。这不应该是需要的。 CURL 会根据作为查询字符串或数组的发布数据将正确的类型放入标头本身。它可以与没有此标头选项的查询字符串一起使用。
  • 使用查询字符串时,标题应为:application/x-www-form-urlencoded 当数组时,标题应为:multipart/form-data

标签: php curl google-api google-cloud-platform


【解决方案1】:

尝试阅读 CURLOPT_POSTFIELDS 的 documentation,你会看到上面写着 要发布文件,请在文件名前加上 @ 并使用完整路径。 这看起来是你想要做的.请注意,在 php 5.5 中,引入了 CURLFile 类来让您发布文件。

如果你使用的是 php 5.5 或更高版本,你可以试试这个:

$url = 'https://script.google.com/a/somedomain.com/macros/s/### script id ###/exec';

// create a CURLFile object:
$cfile = new CURLFile('file.pdf','application/pdf'); // you can also optionally use a third parameter

// your POST data...you may need to add other data here like api keys and stuff
$data = array("fileName" => $cfile);

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);

// FROM THE DOCS:
// If value is an array, the Content-Type header will be set to multipart/form-data (so you might skip the line above)
// As of PHP 5.2.0, value must be an array if files are passed to this option with the @ prefix
// As of PHP 5.5.0, the @ prefix is deprecated and files can be sent using CURLFile
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

// set this to TRUE if you want curl_exec to retrieve the result
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch);
if ($result === FALSE) {
    echo "The result is FALSE. There was a problem\n";
    $error  = curl_error($ch);
    var_dump($error);
    die();
} else {
    echo "success!\n";
    var_dump($result);
}

// this can give you more information about your request
$info = curl_getinfo($ch);
if ($info === FALSE) {
    echo "curlinfo is FALSE! Something weird happened";
}
var_dump($info); // examine this output for clues

编辑:如果您没有收到任何错误,并且 $result 返回类似“Bad Request”的内容,那么您需要更仔细地检查结果以找出问题所在。一个表现良好的 API 应该有丰富的信息来帮助您解决问题。如果 API 没有告诉您您做错了什么,您可以检查从以下命令获得的 curlinfo:

$info = curl_getinfo($ch);
var_dump($info); // examine this output for clues

如果 $result 和 $info 没有告诉您您做错了什么,请尝试更仔细地阅读 API 文档。您可能会在其中的某个地方找到线索。

如果您无法弄清楚使用这些策略的问题所在,那么您就无法对您的代码做任何其他事情了。您需要从 API 的维护者那里获得更多信息。

【讨论】:

  • 很抱歉给您带来了困惑。我不是要发布文件。只是文字。为了清楚起见,我更新了问题。
  • @TimDuncklee 我编辑了我的帖子以提供更多信息。不幸的是,除了我在这里发布的内容之外,您无能为力。如果您收到“错误请求”,那么您需要从 API 或 API 文档中找出您做错了什么。
  • curl_getinfo($ch) 什么也不返回。我认为谷歌根本不够可靠,无法使用。它是随机的,但有时我可以用 doGET() 做同样的事情,但它通常也会返回错误。稍后运行完全相同的代码,无需更改代码并且它可以工作。我想做的是微不足道的,我在谷歌之外做过很多次。应该没那么难。
  • @TimDuncklee 这不太可能是 Google 错误。根据返回的错误请求消息,传递的参数很可能有问题。
  • @S. Imp 我没有尝试您的代码,因为我没有尝试上传文件。 curl_getinfo 正在返回有效信息。这都是我的错。当我到达断点时,我没有注意到我正在覆盖返回的值。感谢您的帮助!
【解决方案2】:

您需要查看您的 HTTP 请求标头以了解实际发布的内容。

在排除故障时,我会添加以下选项:

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_ENCODING,"");

curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

CURLINFO_HEADER_OUT 会将"request_header" 添加到curl_getinfo()

您还想查看这些 curl_getinfo() 元素。

  • request_size
  • size_upload
  • 上传内容长度
  • request_header

【讨论】:

  • 谢谢。你的帖子。它让我找到了正确的方向。我已经用修复更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多