PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求。
传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:
1
2
3
4
5
curl_setopt(ch,
CURLOPT_POSTFIELDS, array(
'file' => '@'.realpath('image.png'),
));
equals
$ curl -F "file=@/absolute/path/to/image.png"
但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细定义MIME类型、文件名等可能出现在multipart/form-data数据中的附加信息。PHP推荐使用CURLFile替代旧的@语法:
1
2
3
curl_setopt(ch,
CURLOPT_POSTFIELDS, [
'file' => new
CURLFile(realpath('image.png')),
]);
PHP
5.5另外引入了CURL_SAFE_UPLOAD选项,可以强制PHP的cURL模块拒绝旧的@语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。
微信公众号多媒体上传接口返回码出现41005的原因就是不能识别文件.
归根到底,可能开发者没有太在乎php版本之间的更新和差异,所以导致在低版本的php环境开发的,然后部署到高版本的环境中.
需要注意的是php5.4 php5.5
php5.6三个版本都有所不同.下面我贴出一段上传图片代码,供大家参考(能兼容三个版本):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$filepath = dirname (
__FILE__ ) . "/a.jpg";
if (class_exists (
'\CURLFile' ))
{//关键是判断curlfile,官网推荐php5.5或更高的版本使用curlfile来实例文件
$filedata = array (
'fieldname' => new \CURLFile
( realpath ( $filepath ), 'image/jpeg'
)
);
} else {
$filedata = array (
'fieldname' => '@' . realpath (
$filepath )
);
}
$url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token="
. $access_token . "&type=image";
$result = Http::upload (
$url, $filedata
);//调用upload函数
if (isset ( $result ))
{
$data = json_decode (
$result );
if (isset ( $data->media_id )) {
$this->responseText (
$data->media_id
);//这是我自己封装的返回消息函数
} else {
$this->responseImg (
"not set
media_id" );//这是我自己封装的返回消息函数
}
} else {
$this->responseText (
"no
response" );//这是我自己封装的返回消息函数
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static function
upload($url, $filedata) {
$curl = curl_init
();
if (class_exists (
'/CURLFile' ))
{//php5.5跟php5.6中的CURLOPT_SAFE_UPLOAD的默认值不同
curl_setopt ( $curl,
CURLOPT_SAFE_UPLOAD, true );
} else {
if (defined (
'CURLOPT_SAFE_UPLOAD' ))
{
curl_setopt ( $curl,
CURLOPT_SAFE_UPLOAD, false );
}
}
curl_setopt ( $curl,
CURLOPT_URL, $url );
curl_setopt ( $curl,
CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt ( $curl,
CURLOPT_SSL_VERIFYHOST, FALSE );
if (! empty (
$filedata )) {
curl_setopt ( $curl,
CURLOPT_POST, 1 );
curl_setopt ( $curl,
CURLOPT_POSTFIELDS, $filedata );
}
curl_setopt ( $curl,
CURLOPT_RETURNTRANSFER, 1 );
$output = curl_exec (
$curl );
curl_close ( $curl );
return $output;
}