从 PHP 5.5 升级到 5.6 后,我的 cURL 上传失败:
$aPost = array(
'file' => "@".$localFile,
'default_file' => 'html_version.html',
'expiration' => (2*31*24*60*60)
)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);
该文件在目标系统上似乎是空的。
其实我在开始提问的时候就找到了答案。 PHP 5.5 中的 curl 包含一个新变量:
CURLOPT_SAFE_UPLOAD
,在 PHP 5.5 中默认设置为 false
,在 PHP 5.6 中切换为默认值 true
。
出于安全原因,这将阻止“@”上传修饰符工作 - 用户输入可能包含恶意上传请求。当
CURLFile
设置为 CURLOPT_SAFE_UPLOAD
时,您可以使用 true
类上传文件,或者(如果您确定变量是安全的,您可以手动将 CURLOPT_SAFE_UPLOAD
切换为 false
):
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
这是让我朝着正确方向搜索的信息来源:http://comments.gmane.org/gmane.comp.php.devel/87521
在更改的函数中也提到了:http://php.net/manual/en/migration56.changed-functions.php 但不是在向后不兼容的变化,真的让我失望......
只需对 PHP 5.5 或更高版本进行以下更改即可
不用
"@" . $localFile
只需使用 new CurlFile($localFile)
并设置
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
包括运行时检查,以使您的代码也与较低版本兼容,如下所示
$aPost = array(
'default_file' => 'html_version.html',
'expiration' => (2*31*24*60*60)
)
if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
$aPost['file'] = new CURLFile($localFile);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
} else {
$aPost['file'] = "@".$localFile;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);
CURLOPT_SAFE_UPLOAD
在 PHP 7 及更高版本中已弃用。使用它会抛出异常(已在 PHP 8 上验证),因为它已被删除:
注意:PHP 消息:PHP 致命错误:未捕获 ValueError:curl_setopt():不再支持禁用安全上传
在文档中有一条通知,这始终是正确的。不幸的是,没有任何信息表明它已被删除以及您应该如何处理文件上传。 PHP 为此提供了
CURLFile
。以下示例适用于 PHP 8:
$file = new CURLFile($path, 'image/png', $name);
$data = array('tags' => 'example-of-other-form-fields','file' => $file);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://my-image-hoster.com/api.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
var_dump($header, $body);
$path
是文件系统上的本地路径,即您要上传的文件所在的位置。$name
设置 HTTP POST 表单中的图像名称。服务器可以使用该名称。例如,当目标服务器也使用 PHP 时,您将从 $_FILES['file']['name']
$data
数组。 (php)服务器将在 $_POST
中找到它们,就像我的示例中的 $_POST['tags']