最近,在08cms的新核心系统开发中,需要开发远程附件上传功能,具体需求就是把A服务器上的系统上传的附件,保存在B服务器中,并把有关图片信息保存到A服务器的系统中。
一、首先,查询网上的方法,实现如:
1.PHP开启CURL扩展支持。
2.注意服务器文件夹的权限。
3.直接上代码
本地代码如下:
<?php
header('content-type:text/html;charset=utf8');
$curl = curl_init();
$data = array('img'=>'@'. dirname(__FILE__).'/img/login.gif');
curl_setopt($curl, CURLOPT_URL, "http://www.demo.com/uploadimg.php");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($curl);
curl_close($curl);
echo json_decode($result);
远程服务器接受端代码:
<?php
if($_FILES)
{
$filename = $_FILES['img']['name'];
$tmpname = $_FILES['img']['tmp_name'];
if(move_uploaded_file($tmpname, dirname(__FILE__).'/img/'.$filename))
{
echo json_encode('上传成功');
} else {
$data = json_encode($_FILES);
echo $data;
}
}
?>
二、接着,根据不同版本PHP之间cURL的区别,修改如下:
传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:
curl_setopt(ch, CURLOPT_POSTFIELDS, array(
'file' => '@'.realpath('image.png'),
));
equals
$ curl -F "file=@/absolute/path/to/image.png" <url>
但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细定义MIME类型、文件名等可能出现在multipart/form-data数据中的附加信息。PHP推荐使用CURLFile替代旧的@语法:
curl_setopt(ch, CURLOPT_POSTFIELDS, [
'file' => new CURLFile(realpath('image.png')),
]);
三、然后,根据以上方法,整理代码如下:
08cms新核心 FileUpload.php
代码如下:
//php 5.5以上的用法
if(class_exists('\CURLFile'))
$postData = array('photo' => new \CURLFile(realpath($fileTmp), $fileType, $fileName));
else
$postData = array('photo' => '@'.realpath($fileTmp).";type=".$fileType.";filename=".$fileName);
header('content-type:text/html;charset=utf8');
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $postUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
curl_exec($curl);
$data = curl_multi_getcontent($curl);//CURL获取返回值方法,下文解释
curl_close($curl);
远程服务器接受端 imgUpload.php
代码:
<?php
if($_FILES)
{
$tmpName = $_FILES['photo']['tmp_name'];
$fileName = $_FILES['photo']['name'];
$uploadFile = dirname(__FILE__).DIRECTORY_SEPARATOR.'img'.DIRECTORY_SEPARATOR.basename($fileName);
if(move_uploaded_file($tmpName, $uploadFile))
{
echo json_encode('上传成功');
}
else
{
$data = json_encode($_FILES);
echo $data;
}
}
?>
四、后面,根据开发需求,作出以下调整:
根据本次远程上传文件功能设计,本地发送端 和 远程服务器接受端 均为08cms新核心系统,即 A服务器 新核心系统 远程上传文件至 B服务器新核心系统 本地保存,如下:
A服务器系统(附件设置:远程上传)->B服务器系统(附件设置:本地上传)
所以,A端上传文件至B端,由B端负责接受文件,生成随机文件名和目录,保存文件并返回有关(文件)信息;A端需接受返回信息,处理保存并生成缩略图。
备注:B端亦为相同系统,也会处理保存并生成缩略图,但本次操作不需要这些数据,可忽略。
由上得知,需要获取curl的返回值。
$result= curl_exec($curl);
echo json_decode($result);
然而,curl_exec()
执行给定的cURL
会话,直接获取成功时返回 TRUE
, 或者在失败时返回 FALSE
。 如果 CURLOPT_RETURNTRANSFER
选项被设置,函数执行成功时会返回执行的结果,失败时返回 FALSE
。并不能直接获取返回值,并进行操作处理。
于是,便找到了PHP CURL
获取返回值的方法——
curl_multi_getcontent( resource $ch )
在CURL
中有一个参数 CURLOPT_RETURNTRANSFER
:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
默认是 0
直接返回获取的输出的文本流,有时候,我们要拿返回值来做判断或者做其他用途的话那就不太好了。
幸好CURLOPT_RETURNTRANSFER
可以设置,如果设置成CURLOPT_RETURNTRANSFER 1
:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
那么就可以在没有curl_close
关闭一个cURL会话前使用:
curl_multi_getcontent($ch)
就能取到服务器返回给我们的值了。是字符串类型!
curl_multi_getcontent( resource $ch )
如果CURLOPT_RETURNTRANSFER
作为一个选项被设置到一个具体的句柄,那么这个函数将会以字符串的形式返回那个cURL
句柄获取的内容。
所以,只需要在B端接受方法中输出所需信息,以文本流形式返回到A端,最后根据字符串截取获取信息,并作进一步处理。
B端 输出代码:
//输出文件提交信息,构造返回信息
echo $this->parameters["error"]."|";
echo $this->parameters["msg"]."|";
echo $this->parameters["name"];
A端 处理代码:
//构造返回信息
$length = strpos($data, "\n");
$str = substr($data, 0, $length);
$fileData = explode("|", $str);
$saveName = $fileData[2];
$saveFileName = $fileData[1];
$saveFilePath = str_replace($saveName, "", $saveFileName);
$saveFilePath = substr($saveFilePath, 0, strlen($saveFilePath)-1);
$saveFilePath = str_replace("/", "\\", $saveFilePath);
最后,系统根据获取所需的信息,保存数据并生成缩略图。
参考网址: