扩展库
This commit is contained in:
175
extend/org/upload/driver/Ftp.php
Normal file
175
extend/org/upload/driver/Ftp.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace org\upload\driver;
|
||||
|
||||
use think\Exception;
|
||||
|
||||
class Ftp
|
||||
{
|
||||
/**
|
||||
* 上传文件根目录
|
||||
* @var string
|
||||
*/
|
||||
private $rootPath;
|
||||
|
||||
/**
|
||||
* 本地上传错误信息
|
||||
* @var string
|
||||
*/
|
||||
private $error = ''; //上传错误信息
|
||||
|
||||
/**
|
||||
* FTP连接
|
||||
* @var resource
|
||||
*/
|
||||
private $link;
|
||||
|
||||
private $config = [
|
||||
'host' => '', //服务器
|
||||
'port' => 21, //端口
|
||||
'timeout' => 90, //超时时间
|
||||
'username' => '', //用户名
|
||||
'password' => '', //密码
|
||||
];
|
||||
|
||||
/**
|
||||
* 构造函数,用于设置上传根路径
|
||||
* @param array $config FTP配置
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
/* 默认FTP配置 */
|
||||
$this->config = array_merge($this->config, $config);
|
||||
|
||||
/* 登录FTP服务器 */
|
||||
if (!$this->login()) {
|
||||
throw new Exception($this->error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传根目录
|
||||
* @param string $rootpath 根目录
|
||||
* @return boolean true-检测通过,false-检测失败
|
||||
*/
|
||||
public function checkRootPath($rootpath)
|
||||
{
|
||||
/* 设置根目录 */
|
||||
$this->rootPath = ftp_pwd($this->link) . '/' . ltrim($rootpath, '/');
|
||||
|
||||
if (!@ftp_chdir($this->link, $this->rootPath)) {
|
||||
$this->error = '上传根目录不存在!';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传目录
|
||||
* @param string $savepath 上传目录
|
||||
* @return boolean 检测结果,true-通过,false-失败
|
||||
*/
|
||||
public function checkSavePath($savepath)
|
||||
{
|
||||
/* 检测并创建目录 */
|
||||
if (!$this->mkdir($savepath)) {
|
||||
return false;
|
||||
} else {
|
||||
//TODO:检测目录是否可写
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存指定文件
|
||||
* @param array $file 保存的文件信息
|
||||
* @param boolean $replace 同名文件是否覆盖
|
||||
* @return boolean 保存状态,true-成功,false-失败
|
||||
*/
|
||||
public function save($file, $replace = true)
|
||||
{
|
||||
$filename = $this->rootPath . $file['savepath'] . $file['savename'];
|
||||
|
||||
/* 不覆盖同名文件 */
|
||||
// if (!$replace && is_file($filename)) {
|
||||
// $this->error = '存在同名文件' . $file['savename'];
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/* 移动文件 */
|
||||
if (!ftp_put($this->link, $filename, $file['tmp_name'], FTP_BINARY)) {
|
||||
$this->error = '文件上传保存错误!';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建目录
|
||||
* @param string $savepath 要创建的目录
|
||||
* @return boolean 创建状态,true-成功,false-失败
|
||||
*/
|
||||
public function mkdir($savepath)
|
||||
{
|
||||
$dir = $this->rootPath . $savepath;
|
||||
if (ftp_chdir($this->link, $dir)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ftp_mkdir($this->link, $dir)) {
|
||||
return true;
|
||||
} elseif ($this->mkdir(dirname($savepath)) && ftp_mkdir($this->link, $dir)) {
|
||||
return true;
|
||||
} else {
|
||||
$this->error = "目录 {$savepath} 创建失败!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一次上传错误信息
|
||||
* @return string 错误信息
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录到FTP服务器
|
||||
* @return boolean true-登录成功,false-登录失败
|
||||
*/
|
||||
private function login()
|
||||
{
|
||||
extract($this->config);
|
||||
$this->link = ftp_connect($host, $port, $timeout);
|
||||
if ($this->link) {
|
||||
if (ftp_login($this->link, $username, $password)) {
|
||||
return true;
|
||||
} else {
|
||||
$this->error = "无法登录到FTP服务器:username - {$username}";
|
||||
}
|
||||
} else {
|
||||
$this->error = "无法连接到FTP服务器:{$host}";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 析构方法,用于断开当前FTP连接
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
ftp_close($this->link);
|
||||
}
|
||||
|
||||
}
|
||||
126
extend/org/upload/driver/Local.php
Normal file
126
extend/org/upload/driver/Local.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace org\upload\driver;
|
||||
|
||||
class Local
|
||||
{
|
||||
/**
|
||||
* 上传文件根目录
|
||||
* @var string
|
||||
*/
|
||||
private $rootPath;
|
||||
|
||||
/**
|
||||
* 本地上传错误信息
|
||||
* @var string
|
||||
*/
|
||||
private $error = ''; //上传错误信息
|
||||
|
||||
/**
|
||||
* 构造函数,用于设置上传根路径
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传根目录
|
||||
* @param string $rootpath 根目录
|
||||
* @return boolean true-检测通过,false-检测失败
|
||||
*/
|
||||
public function checkRootPath($rootpath)
|
||||
{
|
||||
if (!(is_dir($rootpath) && is_writable($rootpath))) {
|
||||
$this->error = '上传根目录不存在!请尝试手动创建:' . $rootpath;
|
||||
return false;
|
||||
}
|
||||
$this->rootPath = $rootpath;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传目录
|
||||
* @param string $savepath 上传目录
|
||||
* @return boolean 检测结果,true-通过,false-失败
|
||||
*/
|
||||
public function checkSavePath($savepath)
|
||||
{
|
||||
/* 检测并创建目录 */
|
||||
if (!$this->mkdir($savepath)) {
|
||||
return false;
|
||||
} else {
|
||||
/* 检测目录是否可写 */
|
||||
if (!is_writable($this->rootPath . $savepath)) {
|
||||
$this->error = '上传目录 ' . $savepath . ' 不可写!';
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存指定文件
|
||||
* @param array $file 保存的文件信息
|
||||
* @param boolean $replace 同名文件是否覆盖
|
||||
* @return boolean 保存状态,true-成功,false-失败
|
||||
*/
|
||||
public function save($file, $replace = true)
|
||||
{
|
||||
$filename = $this->rootPath . $file['savepath'] . $file['savename'];
|
||||
|
||||
/* 不覆盖同名文件 */
|
||||
if (!$replace && is_file($filename)) {
|
||||
$this->error = '存在同名文件' . $file['savename'];
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 移动文件 */
|
||||
if (!move_uploaded_file($file['tmp_name'], $filename)) {
|
||||
$this->error = '文件上传保存错误!';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建目录
|
||||
* @param string $savepath 要创建的目录
|
||||
* @return boolean 创建状态,true-成功,false-失败
|
||||
*/
|
||||
public function mkdir($savepath)
|
||||
{
|
||||
$dir = $this->rootPath . $savepath;
|
||||
if (is_dir($dir)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mkdir($dir, 0777, true)) {
|
||||
return true;
|
||||
} else {
|
||||
$this->error = "目录 {$savepath} 创建失败!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一次上传错误信息
|
||||
* @return string 错误信息
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
}
|
||||
110
extend/org/upload/driver/Qiniu.php
Normal file
110
extend/org/upload/driver/Qiniu.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yangweijie <yangweijiester@gmail.com> <http://www.code-tech.diandian.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace org\upload\driver;
|
||||
|
||||
use org\upload\driver\qiniu\QiniuStorage;
|
||||
|
||||
class Qiniu
|
||||
{
|
||||
/**
|
||||
* 上传文件根目录
|
||||
* @var string
|
||||
*/
|
||||
private $rootPath;
|
||||
|
||||
/**
|
||||
* 上传错误信息
|
||||
* @var string
|
||||
*/
|
||||
private $error = '';
|
||||
|
||||
private $config = [
|
||||
'secretKey' => '', //七牛服务器
|
||||
'accessKey' => '', //七牛用户
|
||||
'domain' => '', //七牛密码
|
||||
'bucket' => '', //空间名称
|
||||
'timeout' => 300, //超时时间
|
||||
];
|
||||
|
||||
/**
|
||||
* 构造函数,用于设置上传根路径
|
||||
* @param array $config FTP配置
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = array_merge($this->config, $config);
|
||||
/* 设置根目录 */
|
||||
$this->qiniu = new QiniuStorage($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传根目录(七牛上传时支持自动创建目录,直接返回)
|
||||
* @param string $rootpath 根目录
|
||||
* @return boolean true-检测通过,false-检测失败
|
||||
*/
|
||||
public function checkRootPath($rootpath)
|
||||
{
|
||||
$this->rootPath = trim($rootpath, './') . '/';
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传目录(七牛上传时支持自动创建目录,直接返回)
|
||||
* @param string $savepath 上传目录
|
||||
* @return boolean 检测结果,true-通过,false-失败
|
||||
*/
|
||||
public function checkSavePath($savepath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件夹 (七牛上传时支持自动创建目录,直接返回)
|
||||
* @param string $savepath 目录名称
|
||||
* @return boolean true-创建成功,false-创建失败
|
||||
*/
|
||||
public function mkdir($savepath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存指定文件
|
||||
* @param array $file 保存的文件信息
|
||||
* @param boolean $replace 同名文件是否覆盖
|
||||
* @return boolean 保存状态,true-成功,false-失败
|
||||
*/
|
||||
public function save(&$file, $replace = true)
|
||||
{
|
||||
$file['name'] = $file['savepath'] . $file['savename'];
|
||||
$key = str_replace('/', '_', $file['name']);
|
||||
$upfile = [
|
||||
'name' => 'file',
|
||||
'fileName' => $key,
|
||||
'fileBody' => file_get_contents($file['tmp_name']),
|
||||
];
|
||||
$config = [];
|
||||
$result = $this->qiniu->upload($config, $upfile);
|
||||
$url = $this->qiniu->downlink($key);
|
||||
$file['url'] = $url;
|
||||
return false === $result ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一次上传错误信息
|
||||
* @return string 错误信息
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->qiniu->errorStr;
|
||||
}
|
||||
}
|
||||
114
extend/org/upload/driver/Sae.php
Normal file
114
extend/org/upload/driver/Sae.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: luofei614<weibo.com/luofei614>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace org\upload\driver;
|
||||
|
||||
class Sae
|
||||
{
|
||||
/**
|
||||
* Storage的Domain
|
||||
* @var string
|
||||
*/
|
||||
private $domain = '';
|
||||
|
||||
private $rootPath = '';
|
||||
|
||||
/**
|
||||
* 本地上传错误信息
|
||||
* @var string
|
||||
*/
|
||||
private $error = '';
|
||||
|
||||
/**
|
||||
* 构造函数,设置storage的domain, 如果有传配置,则domain为配置项,如果没有传domain为第一个路径的目录名称。
|
||||
* @param mixed $config 上传配置
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
{
|
||||
if (is_array($config) && !empty($config['domain'])) {
|
||||
$this->domain = strtolower($config['domain']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传根目录
|
||||
* @param string $rootpath 根目录
|
||||
* @return boolean true-检测通过,false-检测失败
|
||||
*/
|
||||
public function checkRootPath($rootpath)
|
||||
{
|
||||
$rootpath = trim($rootpath, './');
|
||||
if (!$this->domain) {
|
||||
$rootpath = explode('/', $rootpath);
|
||||
$this->domain = strtolower(array_shift($rootpath));
|
||||
$rootpath = implode('/', $rootpath);
|
||||
}
|
||||
|
||||
$this->rootPath = $rootpath;
|
||||
$st = new \SaeStorage();
|
||||
if (false === $st->getDomainCapacity($this->domain)) {
|
||||
$this->error = '您好像没有建立Storage的domain[' . $this->domain . ']';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传目录
|
||||
* @param string $savepath 上传目录
|
||||
* @return boolean 检测结果,true-通过,false-失败
|
||||
*/
|
||||
public function checkSavePath($savepath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存指定文件
|
||||
* @param array $file 保存的文件信息
|
||||
* @param boolean $replace 同名文件是否覆盖
|
||||
* @return boolean 保存状态,true-成功,false-失败
|
||||
*/
|
||||
public function save(&$file, $replace = true)
|
||||
{
|
||||
$filename = ltrim($this->rootPath . '/' . $file['savepath'] . $file['savename'], '/');
|
||||
$st = new \SaeStorage();
|
||||
/* 不覆盖同名文件 */
|
||||
if (!$replace && $st->fileExists($this->domain, $filename)) {
|
||||
$this->error = '存在同名文件' . $file['savename'];
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 移动文件 */
|
||||
if (!$st->upload($this->domain, $filename, $file['tmp_name'])) {
|
||||
$this->error = '文件上传保存错误![' . $st->errno() . ']:' . $st->errmsg();
|
||||
return false;
|
||||
} else {
|
||||
$file['url'] = $st->getUrl($this->domain, $filename);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function mkdir()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一次上传错误信息
|
||||
* @return string 错误信息
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
}
|
||||
230
extend/org/upload/driver/Upyun.php
Normal file
230
extend/org/upload/driver/Upyun.php
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace org\upload\driver;
|
||||
|
||||
class Upyun
|
||||
{
|
||||
/**
|
||||
* 上传文件根目录
|
||||
* @var string
|
||||
*/
|
||||
private $rootPath;
|
||||
|
||||
/**
|
||||
* 上传错误信息
|
||||
* @var string
|
||||
*/
|
||||
private $error = '';
|
||||
|
||||
private $config = [
|
||||
'host' => '', //又拍云服务器
|
||||
'username' => '', //又拍云用户
|
||||
'password' => '', //又拍云密码
|
||||
'bucket' => '', //空间名称
|
||||
'timeout' => 90, //超时时间
|
||||
];
|
||||
|
||||
/**
|
||||
* 构造函数,用于设置上传根路径
|
||||
* @param array $config FTP配置
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
/* 默认FTP配置 */
|
||||
$this->config = array_merge($this->config, $config);
|
||||
$this->config['password'] = md5($this->config['password']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传根目录(又拍云上传时支持自动创建目录,直接返回)
|
||||
* @param string $rootpath 根目录
|
||||
* @return boolean true-检测通过,false-检测失败
|
||||
*/
|
||||
public function checkRootPath($rootpath)
|
||||
{
|
||||
/* 设置根目录 */
|
||||
$this->rootPath = trim($rootpath, './') . '/';
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传目录(又拍云上传时支持自动创建目录,直接返回)
|
||||
* @param string $savepath 上传目录
|
||||
* @return boolean 检测结果,true-通过,false-失败
|
||||
*/
|
||||
public function checkSavePath($savepath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件夹 (又拍云上传时支持自动创建目录,直接返回)
|
||||
* @param string $savepath 目录名称
|
||||
* @return boolean true-创建成功,false-创建失败
|
||||
*/
|
||||
public function mkdir($savepath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存指定文件
|
||||
* @param array $file 保存的文件信息
|
||||
* @param boolean $replace 同名文件是否覆盖
|
||||
* @return boolean 保存状态,true-成功,false-失败
|
||||
*/
|
||||
public function save($file, $replace = true)
|
||||
{
|
||||
$header['Content-Type'] = $file['type'];
|
||||
$header['Content-MD5'] = $file['md5'];
|
||||
$header['Mkdir'] = 'true';
|
||||
$resource = fopen($file['tmp_name'], 'r');
|
||||
|
||||
$save = $this->rootPath . $file['savepath'] . $file['savename'];
|
||||
$data = $this->request($save, 'PUT', $header, $resource);
|
||||
return false === $data ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一次上传错误信息
|
||||
* @return string 错误信息
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求又拍云服务器
|
||||
* @param string $path 请求的PATH
|
||||
* @param string $method 请求方法
|
||||
* @param array $headers 请求header
|
||||
* @param resource $body 上传文件资源
|
||||
* @return boolean
|
||||
*/
|
||||
private function request($path, $method, $headers = null, $body = null)
|
||||
{
|
||||
$uri = "/{$this->config['bucket']}/{$path}";
|
||||
$ch = curl_init($this->config['host'] . $uri);
|
||||
|
||||
$_headers = ['Expect:'];
|
||||
if (!is_null($headers) && is_array($headers)) {
|
||||
foreach ($headers as $k => $v) {
|
||||
array_push($_headers, "{$k}: {$v}");
|
||||
}
|
||||
}
|
||||
|
||||
$length = 0;
|
||||
$date = gmdate('D, d M Y H:i:s \G\M\T');
|
||||
|
||||
if (!is_null($body)) {
|
||||
if (is_resource($body)) {
|
||||
fseek($body, 0, SEEK_END);
|
||||
$length = ftell($body);
|
||||
fseek($body, 0);
|
||||
|
||||
array_push($_headers, "Content-Length: {$length}");
|
||||
curl_setopt($ch, CURLOPT_INFILE, $body);
|
||||
curl_setopt($ch, CURLOPT_INFILESIZE, $length);
|
||||
} else {
|
||||
$length = @strlen($body);
|
||||
array_push($_headers, "Content-Length: {$length}");
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
}
|
||||
} else {
|
||||
array_push($_headers, "Content-Length: {$length}");
|
||||
}
|
||||
|
||||
array_push($_headers, 'Authorization: ' . $this->sign($method, $uri, $date, $length));
|
||||
array_push($_headers, "Date: {$date}");
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $this->config['timeout']);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
|
||||
if ('PUT' == $method || 'POST' == $method) {
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_POST, 0);
|
||||
}
|
||||
|
||||
if ('HEAD' == $method) {
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true);
|
||||
}
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
list($header, $body) = explode("\r\n\r\n", $response, 2);
|
||||
|
||||
if (200 == $status) {
|
||||
if ('GET' == $method) {
|
||||
return $body;
|
||||
} else {
|
||||
$data = $this->response($header);
|
||||
return count($data) > 0 ? $data : true;
|
||||
}
|
||||
} else {
|
||||
$this->error($header);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取响应数据
|
||||
* @param string $text 响应头字符串
|
||||
* @return array 响应数据列表
|
||||
*/
|
||||
private function response($text)
|
||||
{
|
||||
$headers = explode("\r\n", $text);
|
||||
$items = [];
|
||||
foreach ($headers as $header) {
|
||||
$header = trim($header);
|
||||
if (strpos($header, 'x-upyun') !== false) {
|
||||
list($k, $v) = explode(':', $header);
|
||||
$items[trim($k)] = in_array(substr($k, 8, 5), ['width', 'heigh', 'frame']) ? intval($v) : trim($v);
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求签名
|
||||
* @param string $method 请求方法
|
||||
* @param string $uri 请求URI
|
||||
* @param string $date 请求时间
|
||||
* @param integer $length 请求内容大小
|
||||
* @return string 请求签名
|
||||
*/
|
||||
private function sign($method, $uri, $date, $length)
|
||||
{
|
||||
$sign = "{$method}&{$uri}&{$date}&{$length}&{$this->config['password']}";
|
||||
return 'UpYun ' . $this->config['username'] . ':' . md5($sign);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求错误信息
|
||||
* @param string $header 请求返回头信息
|
||||
*/
|
||||
private function error($header)
|
||||
{
|
||||
list($status, $stash) = explode("\r\n", $header, 2);
|
||||
list($v, $code, $message) = explode(" ", $status, 3);
|
||||
$message = is_null($message) ? 'File Not Found' : "[{$status}]:{$message}";
|
||||
$this->error = $message;
|
||||
}
|
||||
|
||||
}
|
||||
366
extend/org/upload/driver/qiniu/QiniuStorage.php
Normal file
366
extend/org/upload/driver/qiniu/QiniuStorage.php
Normal file
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
namespace org\upload\driver\qiniu;
|
||||
|
||||
class QiniuStorage
|
||||
{
|
||||
|
||||
public $QINIU_RSF_HOST = 'http://rsf.qbox.me';
|
||||
public $QINIU_RS_HOST = 'http://rs.qbox.me';
|
||||
public $QINIU_UP_HOST = 'http://up.qiniu.com';
|
||||
public $timeout = '';
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->sk = $config['secretKey'];
|
||||
$this->ak = $config['accessKey'];
|
||||
$this->domain = $config['domain'];
|
||||
$this->bucket = $config['bucket'];
|
||||
$this->timeout = isset($config['timeout']) ? $config['timeout'] : 3600;
|
||||
}
|
||||
|
||||
public static function sign($sk, $ak, $data)
|
||||
{
|
||||
$sign = hash_hmac('sha1', $data, $sk, true);
|
||||
return $ak . ':' . self::qiniuEncode($sign);
|
||||
}
|
||||
|
||||
public static function signWithData($sk, $ak, $data)
|
||||
{
|
||||
$data = self::qiniuEncode($data);
|
||||
return self::sign($sk, $ak, $data) . ':' . $data;
|
||||
}
|
||||
|
||||
public function accessToken($url, $body = '')
|
||||
{
|
||||
$parsed_url = parse_url($url);
|
||||
$path = $parsed_url['path'];
|
||||
$access = $path;
|
||||
if (isset($parsed_url['query'])) {
|
||||
$access .= "?" . $parsed_url['query'];
|
||||
}
|
||||
$access .= "\n";
|
||||
|
||||
if ($body) {
|
||||
$access .= $body;
|
||||
}
|
||||
return self::sign($this->sk, $this->ak, $access);
|
||||
}
|
||||
|
||||
public function UploadToken($sk, $ak, $param)
|
||||
{
|
||||
$param['deadline'] = 0 == $param['Expires'] ? 3600 : $param['Expires'];
|
||||
$param['deadline'] += time();
|
||||
$data = ['scope' => $this->bucket, 'deadline' => $param['deadline']];
|
||||
if (!empty($param['CallbackUrl'])) {
|
||||
$data['callbackUrl'] = $param['CallbackUrl'];
|
||||
}
|
||||
if (!empty($param['CallbackBody'])) {
|
||||
$data['callbackBody'] = $param['CallbackBody'];
|
||||
}
|
||||
if (!empty($param['ReturnUrl'])) {
|
||||
$data['returnUrl'] = $param['ReturnUrl'];
|
||||
}
|
||||
if (!empty($param['ReturnBody'])) {
|
||||
$data['returnBody'] = $param['ReturnBody'];
|
||||
}
|
||||
if (!empty($param['AsyncOps'])) {
|
||||
$data['asyncOps'] = $param['AsyncOps'];
|
||||
}
|
||||
if (!empty($param['EndUser'])) {
|
||||
$data['endUser'] = $param['EndUser'];
|
||||
}
|
||||
$data = json_encode($data);
|
||||
return self::SignWithData($sk, $ak, $data);
|
||||
}
|
||||
|
||||
public function upload($config, $file)
|
||||
{
|
||||
$uploadToken = $this->UploadToken($this->sk, $this->ak, $config);
|
||||
|
||||
$url = "{$this->QINIU_UP_HOST}";
|
||||
$mimeBoundary = md5(microtime());
|
||||
$header = ['Content-Type' => 'multipart/form-data;boundary=' . $mimeBoundary];
|
||||
$data = [];
|
||||
|
||||
$fields = [
|
||||
'token' => $uploadToken,
|
||||
'key' => $config['saveName'] ?: $file['fileName'],
|
||||
];
|
||||
|
||||
if (is_array($config['custom_fields']) && [] !== $config['custom_fields']) {
|
||||
$fields = array_merge($fields, $config['custom_fields']);
|
||||
}
|
||||
|
||||
foreach ($fields as $name => $val) {
|
||||
array_push($data, '--' . $mimeBoundary);
|
||||
array_push($data, "Content-Disposition: form-data; name=\"$name\"");
|
||||
array_push($data, '');
|
||||
array_push($data, $val);
|
||||
}
|
||||
|
||||
//文件
|
||||
array_push($data, '--' . $mimeBoundary);
|
||||
$name = $file['name'];
|
||||
$fileName = $file['fileName'];
|
||||
$fileBody = $file['fileBody'];
|
||||
$fileName = self::qiniuEscapequotes($fileName);
|
||||
array_push($data, "Content-Disposition: form-data; name=\"$name\"; filename=\"$fileName\"");
|
||||
array_push($data, 'Content-Type: application/octet-stream');
|
||||
array_push($data, '');
|
||||
array_push($data, $fileBody);
|
||||
|
||||
array_push($data, '--' . $mimeBoundary . '--');
|
||||
array_push($data, '');
|
||||
|
||||
$body = implode("\r\n", $data);
|
||||
$response = $this->request($url, 'POST', $header, $body);
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function dealWithType($key, $type)
|
||||
{
|
||||
$param = $this->buildUrlParam();
|
||||
$url = '';
|
||||
|
||||
switch ($type) {
|
||||
case 'img':
|
||||
$url = $this->downLink($key);
|
||||
if ($param['imageInfo']) {
|
||||
$url .= '?imageInfo';
|
||||
} else if ($param['exif']) {
|
||||
$url .= '?exif';
|
||||
} else if ($param['imageView']) {
|
||||
$url .= '?imageView/' . $param['mode'];
|
||||
if ($param['w']) {
|
||||
$url .= "/w/{$param['w']}";
|
||||
}
|
||||
|
||||
if ($param['h']) {
|
||||
$url .= "/h/{$param['h']}";
|
||||
}
|
||||
|
||||
if ($param['q']) {
|
||||
$url .= "/q/{$param['q']}";
|
||||
}
|
||||
|
||||
if ($param['format']) {
|
||||
$url .= "/format/{$param['format']}";
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 'video'://TODO 视频处理
|
||||
case 'doc':
|
||||
$url = $this->downLink($key);
|
||||
$url .= '?md2html';
|
||||
if (isset($param['mode'])) {
|
||||
$url .= '/' . (int) $param['mode'];
|
||||
}
|
||||
|
||||
if ($param['cssurl']) {
|
||||
$url .= '/' . self::qiniuEncode($param['cssurl']);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function buildUrlParam()
|
||||
{
|
||||
return $_REQUEST;
|
||||
}
|
||||
|
||||
//获取某个路径下的文件列表
|
||||
public function getList($query = [], $path = '')
|
||||
{
|
||||
$query = array_merge(['bucket' => $this->bucket], $query);
|
||||
$url = "{$this->QINIU_RSF_HOST}/list?" . http_build_query($query);
|
||||
$accessToken = $this->accessToken($url);
|
||||
$response = $this->request($url, 'POST', ['Authorization' => "QBox $accessToken"]);
|
||||
return $response;
|
||||
}
|
||||
|
||||
//获取某个文件的信息
|
||||
public function info($key)
|
||||
{
|
||||
$key = trim($key);
|
||||
$url = "{$this->QINIU_RS_HOST}/stat/" . self::qiniuEncode("{$this->bucket}:{$key}");
|
||||
$accessToken = $this->accessToken($url);
|
||||
$response = $this->request($url, 'POST', [
|
||||
'Authorization' => "QBox $accessToken",
|
||||
]);
|
||||
return $response;
|
||||
}
|
||||
|
||||
//获取文件下载资源链接
|
||||
public function downLink($key)
|
||||
{
|
||||
$key = urlencode($key);
|
||||
$key = self::qiniuEscapequotes($key);
|
||||
$url = "http://{$this->domain}/{$key}";
|
||||
return $url;
|
||||
}
|
||||
|
||||
//重命名单个文件
|
||||
public function rename($file, $new_file)
|
||||
{
|
||||
$key = trim($file);
|
||||
$url = "{$this->QINIU_RS_HOST}/move/" . self::qiniuEncode("{$this->bucket}:{$key}") . '/' . self::qiniuEncode("{$this->bucket}:{$new_file}");
|
||||
trace($url);
|
||||
$accessToken = $this->accessToken($url);
|
||||
$response = $this->request($url, 'POST', ['Authorization' => "QBox $accessToken"]);
|
||||
return $response;
|
||||
}
|
||||
|
||||
//删除单个文件
|
||||
public function del($file)
|
||||
{
|
||||
$key = trim($file);
|
||||
$url = "{$this->QINIU_RS_HOST}/delete/" . self::qiniuEncode("{$this->bucket}:{$key}");
|
||||
$accessToken = $this->accessToken($url);
|
||||
$response = $this->request($url, 'POST', ['Authorization' => "QBox $accessToken"]);
|
||||
return $response;
|
||||
}
|
||||
|
||||
//批量删除文件
|
||||
public function delBatch($files)
|
||||
{
|
||||
$url = $this->QINIU_RS_HOST . '/batch';
|
||||
$ops = [];
|
||||
foreach ($files as $file) {
|
||||
$ops[] = "/delete/" . self::qiniuEncode("{$this->bucket}:{$file}");
|
||||
}
|
||||
$params = 'op=' . implode('&op=', $ops);
|
||||
$url .= '?' . $params;
|
||||
trace($url);
|
||||
$accessToken = $this->accessToken($url);
|
||||
$response = $this->request($url, 'POST', ['Authorization' => "QBox $accessToken"]);
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function qiniuEncode($str)
|
||||
{
|
||||
// URLSafeBase64Encode
|
||||
$find = ['+', '/'];
|
||||
$replace = ['-', '_'];
|
||||
return str_replace($find, $replace, base64_encode($str));
|
||||
}
|
||||
|
||||
public static function qiniuEscapequotes($str)
|
||||
{
|
||||
$find = ["\\", "\""];
|
||||
$replace = ["\\\\", "\\\""];
|
||||
return str_replace($find, $replace, $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求云服务器
|
||||
* @param string $path 请求的PATH
|
||||
* @param string $method 请求方法
|
||||
* @param array $headers 请求header
|
||||
* @param resource $body 上传文件资源
|
||||
* @return boolean
|
||||
*/
|
||||
private function request($path, $method, $headers = null, $body = null)
|
||||
{
|
||||
$ch = curl_init($path);
|
||||
|
||||
$_headers = ['Expect:'];
|
||||
if (!is_null($headers) && is_array($headers)) {
|
||||
foreach ($headers as $k => $v) {
|
||||
array_push($_headers, "{$k}: {$v}");
|
||||
}
|
||||
}
|
||||
|
||||
$length = 0;
|
||||
$date = gmdate('D, d M Y H:i:s \G\M\T');
|
||||
|
||||
if (!is_null($body)) {
|
||||
if (is_resource($body)) {
|
||||
fseek($body, 0, SEEK_END);
|
||||
$length = ftell($body);
|
||||
fseek($body, 0);
|
||||
|
||||
array_push($_headers, "Content-Length: {$length}");
|
||||
curl_setopt($ch, CURLOPT_INFILE, $body);
|
||||
curl_setopt($ch, CURLOPT_INFILESIZE, $length);
|
||||
} else {
|
||||
$length = @strlen($body);
|
||||
array_push($_headers, "Content-Length: {$length}");
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
}
|
||||
} else {
|
||||
array_push($_headers, "Content-Length: {$length}");
|
||||
}
|
||||
|
||||
// array_push($_headers, 'Authorization: ' . $this->sign($method, $uri, $date, $length));
|
||||
array_push($_headers, "Date: {$date}");
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
|
||||
if ('PUT' == $method || 'POST' == $method) {
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_POST, 0);
|
||||
}
|
||||
|
||||
if ('HEAD' == $method) {
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true);
|
||||
}
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
list($header, $body) = explode("\r\n\r\n", $response, 2);
|
||||
if (200 == $status) {
|
||||
if ('GET' == $method) {
|
||||
return $body;
|
||||
} else {
|
||||
return $this->response($response);
|
||||
}
|
||||
} else {
|
||||
$this->error($header, $body);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取响应数据
|
||||
* @param string $text 响应头字符串
|
||||
* @return array 响应数据列表
|
||||
*/
|
||||
private function response($text)
|
||||
{
|
||||
$headers = explode(PHP_EOL, $text);
|
||||
$items = [];
|
||||
foreach ($headers as $header) {
|
||||
$header = trim($header);
|
||||
if (strpos($header, '{') !== false) {
|
||||
$items = json_decode($header, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求错误信息
|
||||
* @param string $header 请求返回头信息
|
||||
*/
|
||||
private function error($header, $body)
|
||||
{
|
||||
list($status, $stash) = explode("\r\n", $header, 2);
|
||||
list($v, $code, $message) = explode(" ", $status, 3);
|
||||
$message = is_null($message) ? 'File Not Found' : "[{$status}]:{$message}]";
|
||||
$this->error = $message;
|
||||
$this->errorStr = json_decode($body, 1);
|
||||
$this->errorStr = $this->errorStr['error'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user