插件安装

pull/176/head
hnh0000 2020-03-18 09:34:20 +08:00
parent 1836b57ad1
commit 79e202dbd2
484 changed files with 38098 additions and 6 deletions

View File

@ -0,0 +1,96 @@
<?php
namespace addons\alioss;
use OSS\Core\OssException;
use OSS\OssClient;
use think\Addons;
use think\Loader;
/**
* 阿里云OSS上传插件
*/
class Alioss extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
return true;
}
/**
* 添加命名空间
*/
public function appInit()
{
//添加支付包的命名空间
Loader::addNamespace('OSS', ADDON_PATH . 'alioss' . DS . 'library' . DS . 'OSS' . DS);
}
/**
* 加载配置
*/
public function uploadConfigInit(&$upload)
{
$config = $this->getConfig();
if ($config['uploadmode'] === 'client') {
$upload = [
'cdnurl' => $config['cdnurl'],
'uploadurl' => 'https://' . $config['bucket'] . '.' . $config['endpoint'],
'bucket' => $config['bucket'],
'maxsize' => $config['maxsize'],
'mimetype' => $config['mimetype'],
'multipart' => [],
'multiple' => $config['multiple'] ? true : false,
'storage' => 'alioss'
];
} else {
$upload = array_merge($upload, [
'cdnurl' => $config['cdnurl'],
'uploadurl' => addon_url('alioss/index/upload'),
'maxsize' => $config['maxsize'],
'mimetype' => $config['mimetype'],
'multiple' => $config['multiple'] ? true : false,
]);
}
}
/**
* 附件删除后
*/
public function uploadDelete($attachment)
{
$config = $this->getConfig();
if ($attachment['storage'] == 'alioss' && isset($config['syncdelete']) && $config['syncdelete']) {
$endpoint = "http://" . $config['endpoint'];
try {
$ossClient = new OssClient($config['app_id'], $config['app_key'], $endpoint);
$ossClient->deleteObject($config['bucket'], ltrim($attachment->url, '/'));
} catch (OssException $e) {
return false;
}
//如果是服务端中转,还需要删除本地文件
if ($config['uploadmode'] == 'server') {
$filePath = ROOT_PATH . 'public' . str_replace('/', DS, $attachment->url);
if ($filePath) {
@unlink($filePath);
}
}
}
return true;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,104 @@
//如果开启了alioss客户端上传模式
if (typeof Config.upload.storage !== 'undefined' && Config.upload.storage === 'alioss') {
require(['upload', '../addons/alioss/js/spark'], function (Upload, SparkMD5) {
var _onFileAdded = Upload.events.onFileAdded;
var _onUploadResponse = Upload.events.onUploadResponse;
var getFileMd5 = function (file, cb) {
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
file = file.getNative(),
chunkSize = 2097152, // Read in chunks of 2MB
chunks = Math.ceil(file.size / chunkSize),
currentChunk = 0,
spark = new SparkMD5.ArrayBuffer(),
fileReader = new FileReader();
fileReader.onload = function (e) {
spark.append(e.target.result); // Append array buffer
currentChunk++;
if (currentChunk < chunks) {
loadNext();
} else {
cb && cb(spark.end()); // Compute hash
}
};
fileReader.onerror = function () {
console.warn('oops, something went wrong.');
};
function loadNext() {
var start = currentChunk * chunkSize,
end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}
loadNext();
};
var _process = function (up, file) {
(function (up, file) {
getFileMd5(file, function (md5) {
Fast.api.ajax({
url: "/addons/alioss/index/params",
data: {method: 'POST', md5: md5, name: file.name, type: file.type, size: file.size},
}, function (data) {
file.md5 = md5;
file.status = 1;
file.key = data.key;
file.OSSAccessKeyId = data.id;
file.policy = data.policy;
file.signature = data.signature;
up.start();
return false;
});
});
})(up, file);
};
Upload.events.onFileAdded = function (up, files) {
return _onFileAdded.call(this, up, files);
};
Upload.events.onBeforeUpload = function (up, file) {
if (typeof file.md5 === 'undefined') {
up.stop();
_process(up, file);
} else {
up.settings.headers = up.settings.headers || {};
up.settings.multipart_params.key = file.key;
up.settings.multipart_params.OSSAccessKeyId = file.OSSAccessKeyId;
up.settings.multipart_params.success_action_status = 200;
if (typeof file.callback !== 'undefined') {
up.settings.multipart_params.callback = file.callback;
}
up.settings.multipart_params.policy = file.policy;
up.settings.multipart_params.signature = file.signature;
//up.settings.send_file_name = false;
}
};
Upload.events.onUploadResponse = function (response, info, up, file) {
try {
var ret = {};
if (info.status === 200) {
var url = '/' + file.key;
Fast.api.ajax({
url: "/addons/alioss/index/notify",
data: {method: 'POST', name: file.name, url: url, md5: file.md5, size: file.size, type: file.type, policy: file.policy, signature: file.signature}
}, function () {
return false;
});
ret.code = 1;
ret.data = {
url: url
};
} else {
ret.code = 0;
ret.msg = info.response;
}
return _onUploadResponse.call(this, JSON.stringify(ret));
} catch (e) {
}
return _onUploadResponse.call(this, response);
};
});
}

View File

@ -0,0 +1,176 @@
<?php
return array(
array(
'name' => 'app_id',
'title' => 'app_id',
'type' => 'string',
'content' =>
array(),
'value' => 'your app id',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'app_key',
'title' => 'app_key',
'type' => 'string',
'content' =>
array(),
'value' => 'your app key',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'bucket',
'title' => 'Bucket',
'type' => 'string',
'content' =>
array(),
'value' => 'yourbucket',
'rule' => 'required',
'msg' => '',
'tip' => '阿里云OSS的空间名',
'ok' => '',
'extend' => '',
),
array(
'name' => 'endpoint',
'title' => 'EndPoint',
'type' => 'string',
'content' =>
array(),
'value' => 'oss-cn-shenzhen.aliyuncs.com',
'rule' => 'required',
'msg' => '',
'tip' => '如果是服务器中转模式可填写内网域名前面不可加http://',
'ok' => '',
'extend' => '',
),
array(
'name' => 'cdnurl',
'title' => 'CDN地址',
'type' => 'string',
'content' =>
array(),
'value' => 'http://yourbucket.oss-cn-shenzhen.aliyuncs.com',
'rule' => 'required',
'msg' => '',
'tip' => '请填写CDN地址必须以http://开头',
'ok' => '',
'extend' => '',
),
array(
'name' => 'uploadmode',
'title' => '上传模式',
'type' => 'select',
'content' =>
array(
'client' => '客户端直传(速度快,无备份)',
'server' => '服务器中转(占用服务器带宽,有备份)',
),
'value' => 'server',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'savekey',
'title' => '保存文件名',
'type' => 'string',
'content' =>
array(),
'value' => '/uploads/{year}{mon}{day}/{filemd5}{.suffix}',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'expire',
'title' => '上传有效时长',
'type' => 'string',
'content' =>
array(),
'value' => '600',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'maxsize',
'title' => '最大可上传',
'type' => 'string',
'content' =>
array(),
'value' => '10M',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'mimetype',
'title' => '可上传后缀格式',
'type' => 'string',
'content' =>
array(),
'value' => '*',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'multiple',
'title' => '多文件上传',
'type' => 'bool',
'content' =>
array(),
'value' => '0',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => 'syncdelete',
'title' => '附件删除时是否同步删除文件',
'type' => 'bool',
'content' =>
array(),
'value' => '0',
'rule' => 'required',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
array(
'name' => '__tips__',
'title' => '温馨提示',
'type' => '',
'content' =>
array(),
'value' => '在使用之前请注册阿里云账号并进行认证和创建空间,注册链接:<a href="https://oss.console.aliyun.com/index" target="_blank">https://oss.console.aliyun.com/index</a><br/>FastAdmin赠送你阿里云最高1888云产品通用代金券如有需要可以<a href="https://www.fastadmin.net/go/aliyun" target="_blank">点击领取</a>',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
),
);

View File

@ -0,0 +1,188 @@
<?php
namespace addons\alioss\controller;
use app\common\model\Attachment;
use OSS\Core\OssException;
use OSS\OssClient;
use think\addons\Controller;
use think\Config;
/**
* 阿里OSS
*
*/
class Index extends Controller
{
public function index()
{
$this->error("当前插件暂无前台页面");
}
/**
* 获取签名
*/
public function params()
{
Config::set('default_return_type', 'json');
$name = $this->request->post('name');
$md5 = $this->request->post('md5');
$auth = new \addons\alioss\library\Auth();
$params = $auth->params($name, $md5);
$this->success('', null, $params);
return;
}
/**
* 服务器中转上传文件
*/
public function upload()
{
Config::set('default_return_type', 'json');
if (!session('admin') && !$this->auth->id) {
$this->error("请登录后再进行操作");
}
$config = get_addon_config('alioss');
$endpoint = "http://" . $config['endpoint'];
$file = $this->request->file('file');
if (!$file || !$file->isValid()) {
$this->error("请上传有效的文件");
}
$fileInfo = $file->getInfo();
$filePath = $file->getRealPath() ?: $file->getPathname();
preg_match('/(\d+)(\w+)/', $config['maxsize'], $matches);
$type = strtolower($matches[2]);
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
$size = (int)$config['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
$suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
$suffix = $suffix ? $suffix : 'file';
$md5 = md5_file($filePath);
$search = ['{year}', '{mon}', '{month}', '{day}', '{filemd5}', '{suffix}', '{.suffix}'];
$replace = [date("Y"), date("m"), date("m"), date("d"), $md5, $suffix, '.' . $suffix];
$object = ltrim(str_replace($search, $replace, $config['savekey']), '/');
$mimetypeArr = explode(',', strtolower($config['mimetype']));
$typeArr = explode('/', $fileInfo['type']);
//检查文件大小
if (!$file->checkSize($size)) {
$this->error("起过最大可上传文件限制");
}
//验证文件后缀
if ($config['mimetype'] !== '*' &&
(
!in_array($suffix, $mimetypeArr)
|| (stripos($typeArr[0] . '/', $config['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)))
)
) {
$this->error(__('上传格式限制'));
}
$savekey = '/' . $object;
$uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
$fileName = substr($savekey, strripos($savekey, '/') + 1);
//先上传到本地
$splInfo = $file->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
if ($splInfo) {
$extparam = $this->request->post();
$filePath = $splInfo->getRealPath() ?: $splInfo->getPathname();
$sha1 = sha1_file($filePath);
$imagewidth = $imageheight = 0;
if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'])) {
$imgInfo = getimagesize($splInfo->getPathname());
$imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
$imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
}
$params = array(
'admin_id' => session('admin.id'),
'user_id' => $this->auth->id,
'filesize' => $fileInfo['size'],
'imagewidth' => $imagewidth,
'imageheight' => $imageheight,
'imagetype' => $suffix,
'imageframes' => 0,
'mimetype' => $fileInfo['type'],
'url' => $uploadDir . $splInfo->getSaveName(),
'uploadtime' => time(),
'storage' => 'local',
'sha1' => $sha1,
'extparam' => json_encode($extparam),
);
$attachment = new Attachment;
$attachment->data(array_filter($params));
$attachment->save();
//上传到远程
try {
$ossClient = new OssClient($config['app_id'], $config['app_key'], $endpoint);
$ossClient->uploadFile($config['bucket'], $object, $filePath);
} catch (OssException $e) {
$this->error('上传失败');
return;
}
$url = '/' . $object;
//上传成功后将存储变更为alioss
$attachment->storage = 'alioss';
$attachment->save();
$this->success("上传成功", null, ['url' => $url]);
} else {
$this->error('上传失败');
}
return;
}
/**
* 回调
*/
public function notify()
{
Config::set('default_return_type', 'json');
$size = $this->request->post('size');
$name = $this->request->post('name');
$md5 = $this->request->post('md5');
$type = $this->request->post('type');
$signature = $this->request->post('signature');
$policy = $this->request->post('policy');
$url = $this->request->post('url');
$suffix = substr($name, stripos($name, '.') + 1);
$auth = new \addons\alioss\library\Auth();
if ($auth->check($signature, $policy)) {
$attachment = Attachment::getBySha1($md5);
if (!$attachment) {
$params = array(
'admin_id' => (int)session('admin.id'),
'user_id' => (int)cookie('uid'),
'filesize' => $size,
'imagewidth' => 0,
'imageheight' => 0,
'imagetype' => $suffix,
'imageframes' => 0,
'mimetype' => $type,
'url' => $url,
'uploadtime' => time(),
'storage' => 'alioss',
'sha1' => $md5,
);
Attachment::create($params);
}
$this->success();
} else {
$this->error(__('You have no permission'));
}
return;
}
}

View File

@ -0,0 +1,8 @@
name = alioss
title = 阿里OSS上传
intro = 使用阿里OSS存储上传时直传阿里云OSS
author = Karson
website = http://www.fastadmin.net
version = 1.0.3
state = 1
url = /fastadmin/my/public/addons/alioss

View File

@ -0,0 +1,78 @@
<?php
namespace addons\alioss\library;
class Auth
{
public function __construct()
{
}
public function params($name, $md5, $callback = true)
{
$config = get_addon_config('alioss');
$callback_param = array(
'callbackUrl' => isset($config['notifyurl']) ? $config['notifyurl'] : '',
'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
'callbackBodyType' => "application/x-www-form-urlencoded"
);
$base64_callback_body = base64_encode(json_encode($callback_param));
$now = time();
$end = $now + $config['expire']; //设置该policy超时时间是10s. 即这个policy过了这个有效时间将不能访问
$expiration = $this->gmt_iso8601($end);
preg_match('/(\d+)(\w+)/', $config['maxsize'], $matches);
$type = strtolower($matches[2]);
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
$size = (int)$config['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
//最大文件大小.用户可以自己设置
$condition = array(0 => 'content-length-range', 1 => 0, 2 => $size);
$conditions[] = $condition;
//表示用户上传的数据,必须是以$dir开始, 不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录
//$start = array(0 => 'starts-with', 1 => '$key', 2 => $dir);
//$conditions[] = $start;
$arr = array('expiration' => $expiration, 'conditions' => $conditions);
$policy = base64_encode(json_encode($arr));
$signature = base64_encode(hash_hmac('sha1', $policy, $config['app_key'], true));
$suffix = substr($name, stripos($name, '.') + 1);
$search = ['{year}', '{mon}', '{month}', '{day}', '{filemd5}', '{suffix}', '{.suffix}'];
$replace = [date("Y"), date("m"), date("m"), date("d"), $md5, $suffix, '.' . $suffix];
$key = ltrim(str_replace($search, $replace, $config['savekey']), '/');
$response = array();
$response['id'] = $config['app_id'];
$response['key'] = $key;
$response['policy'] = $policy;
$response['signature'] = $signature;
$response['expire'] = $end;
$response['callback'] = '';
return $response;
}
public function check($signature, $policy)
{
$config = get_addon_config('alioss');
$sign = base64_encode(hash_hmac('sha1', $policy, $config['app_key'], true));
return $signature == $sign;
}
private function gmt_iso8601($time)
{
$dtStr = date("c", $time);
$mydatetime = new \DateTime($dtStr);
$expiration = $mydatetime->format(\DateTime::ISO8601);
$pos = strpos($expiration, '+');
$expiration = substr($expiration, 0, $pos);
return $expiration . "Z";
}
}

View File

@ -0,0 +1,262 @@
<?php
namespace OSS\Core;
/**
* Class MimeTypes
*
* 在上传文件的时候根据文件的缺省名得到其对应的Content-type
*
* @package OSS\Core
*/
class MimeTypes
{
/**
* 根据文件名获取http协议header中的content-type应该填写的数据
*
* @param string $name 缺省名
* @return string content-type
*/
public static function getMimetype($name)
{
$parts = explode('.', $name);
if (count($parts) > 1) {
$ext = strtolower(end($parts));
if (isset(self::$mime_types[$ext])) {
return self::$mime_types[$ext];
}
}
return null;
}
private static $mime_types = array(
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'apk' => 'application/vnd.android.package-archive',
'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
'doc' => 'application/msword',
'ogg' => 'audio/ogg',
'pdf' => 'application/pdf',
'rtf' => 'text/rtf',
'mif' => 'application/vnd.mif',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'odc' => 'application/vnd.oasis.opendocument.chart',
'odb' => 'application/vnd.oasis.opendocument.database',
'odf' => 'application/vnd.oasis.opendocument.formula',
'odg' => 'application/vnd.oasis.opendocument.graphics',
'otg' => 'application/vnd.oasis.opendocument.graphics-template',
'odi' => 'application/vnd.oasis.opendocument.image',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'otp' => 'application/vnd.oasis.opendocument.presentation-template',
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
'odt' => 'application/vnd.oasis.opendocument.text',
'odm' => 'application/vnd.oasis.opendocument.text-master',
'ott' => 'application/vnd.oasis.opendocument.text-template',
'oth' => 'application/vnd.oasis.opendocument.text-web',
'sxw' => 'application/vnd.sun.xml.writer',
'stw' => 'application/vnd.sun.xml.writer.template',
'sxc' => 'application/vnd.sun.xml.calc',
'stc' => 'application/vnd.sun.xml.calc.template',
'sxd' => 'application/vnd.sun.xml.draw',
'std' => 'application/vnd.sun.xml.draw.template',
'sxi' => 'application/vnd.sun.xml.impress',
'sti' => 'application/vnd.sun.xml.impress.template',
'sxg' => 'application/vnd.sun.xml.writer.global',
'sxm' => 'application/vnd.sun.xml.math',
'sis' => 'application/vnd.symbian.install',
'wbxml' => 'application/vnd.wap.wbxml',
'wmlc' => 'application/vnd.wap.wmlc',
'wmlsc' => 'application/vnd.wap.wmlscriptc',
'bcpio' => 'application/x-bcpio',
'torrent' => 'application/x-bittorrent',
'bz2' => 'application/x-bzip2',
'vcd' => 'application/x-cdlink',
'pgn' => 'application/x-chess-pgn',
'cpio' => 'application/x-cpio',
'csh' => 'application/x-csh',
'dvi' => 'application/x-dvi',
'spl' => 'application/x-futuresplash',
'gtar' => 'application/x-gtar',
'hdf' => 'application/x-hdf',
'jar' => 'application/java-archive',
'jnlp' => 'application/x-java-jnlp-file',
'js' => 'application/javascript',
'json' => 'application/json',
'ksp' => 'application/x-kspread',
'chrt' => 'application/x-kchart',
'kil' => 'application/x-killustrator',
'latex' => 'application/x-latex',
'rpm' => 'application/x-rpm',
'sh' => 'application/x-sh',
'shar' => 'application/x-shar',
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'sv4cpio' => 'application/x-sv4cpio',
'sv4crc' => 'application/x-sv4crc',
'tar' => 'application/x-tar',
'tcl' => 'application/x-tcl',
'tex' => 'application/x-tex',
'man' => 'application/x-troff-man',
'me' => 'application/x-troff-me',
'ms' => 'application/x-troff-ms',
'ustar' => 'application/x-ustar',
'src' => 'application/x-wais-source',
'zip' => 'application/zip',
'm3u' => 'audio/x-mpegurl',
'ra' => 'audio/x-pn-realaudio',
'wav' => 'audio/x-wav',
'wma' => 'audio/x-ms-wma',
'wax' => 'audio/x-ms-wax',
'pdb' => 'chemical/x-pdb',
'xyz' => 'chemical/x-xyz',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'ief' => 'image/ief',
'png' => 'image/png',
'wbmp' => 'image/vnd.wap.wbmp',
'ras' => 'image/x-cmu-raster',
'pnm' => 'image/x-portable-anymap',
'pbm' => 'image/x-portable-bitmap',
'pgm' => 'image/x-portable-graymap',
'ppm' => 'image/x-portable-pixmap',
'rgb' => 'image/x-rgb',
'xbm' => 'image/x-xbitmap',
'xpm' => 'image/x-xpixmap',
'xwd' => 'image/x-xwindowdump',
'css' => 'text/css',
'rtx' => 'text/richtext',
'tsv' => 'text/tab-separated-values',
'jad' => 'text/vnd.sun.j2me.app-descriptor',
'wml' => 'text/vnd.wap.wml',
'wmls' => 'text/vnd.wap.wmlscript',
'etx' => 'text/x-setext',
'mxu' => 'video/vnd.mpegurl',
'flv' => 'video/x-flv',
'wm' => 'video/x-ms-wm',
'wmv' => 'video/x-ms-wmv',
'wmx' => 'video/x-ms-wmx',
'wvx' => 'video/x-ms-wvx',
'avi' => 'video/x-msvideo',
'movie' => 'video/x-sgi-movie',
'ice' => 'x-conference/x-cooltalk',
'3gp' => 'video/3gpp',
'ai' => 'application/postscript',
'aif' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'asc' => 'text/plain',
'atom' => 'application/atom+xml',
'au' => 'audio/basic',
'bin' => 'application/octet-stream',
'cdf' => 'application/x-netcdf',
'cgm' => 'image/cgm',
'class' => 'application/octet-stream',
'dcr' => 'application/x-director',
'dif' => 'video/x-dv',
'dir' => 'application/x-director',
'djv' => 'image/vnd.djvu',
'djvu' => 'image/vnd.djvu',
'dll' => 'application/octet-stream',
'dmg' => 'application/octet-stream',
'dms' => 'application/octet-stream',
'dtd' => 'application/xml-dtd',
'dv' => 'video/x-dv',
'dxr' => 'application/x-director',
'eps' => 'application/postscript',
'exe' => 'application/octet-stream',
'ez' => 'application/andrew-inset',
'gram' => 'application/srgs',
'grxml' => 'application/srgs+xml',
'gz' => 'application/x-gzip',
'htm' => 'text/html',
'html' => 'text/html',
'ico' => 'image/x-icon',
'ics' => 'text/calendar',
'ifb' => 'text/calendar',
'iges' => 'model/iges',
'igs' => 'model/iges',
'jp2' => 'image/jp2',
'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'kar' => 'audio/midi',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'm4a' => 'audio/mp4a-latm',
'm4p' => 'audio/mp4a-latm',
'm4u' => 'video/vnd.mpegurl',
'm4v' => 'video/x-m4v',
'mac' => 'image/x-macpaint',
'mathml' => 'application/mathml+xml',
'mesh' => 'model/mesh',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mov' => 'video/quicktime',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'mp4' => 'video/mp4',
'mpe' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpga' => 'audio/mpeg',
'msh' => 'model/mesh',
'nc' => 'application/x-netcdf',
'oda' => 'application/oda',
'ogv' => 'video/ogv',
'pct' => 'image/pict',
'pic' => 'image/pict',
'pict' => 'image/pict',
'pnt' => 'image/x-macpaint',
'pntg' => 'image/x-macpaint',
'ps' => 'application/postscript',
'qt' => 'video/quicktime',
'qti' => 'image/x-quicktime',
'qtif' => 'image/x-quicktime',
'ram' => 'audio/x-pn-realaudio',
'rdf' => 'application/rdf+xml',
'rm' => 'application/vnd.rn-realmedia',
'roff' => 'application/x-troff',
'sgm' => 'text/sgml',
'sgml' => 'text/sgml',
'silo' => 'model/mesh',
'skd' => 'application/x-koan',
'skm' => 'application/x-koan',
'skp' => 'application/x-koan',
'skt' => 'application/x-koan',
'smi' => 'application/smil',
'smil' => 'application/smil',
'snd' => 'audio/basic',
'so' => 'application/octet-stream',
'svg' => 'image/svg+xml',
't' => 'application/x-troff',
'texi' => 'application/x-texinfo',
'texinfo' => 'application/x-texinfo',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'tr' => 'application/x-troff',
'txt' => 'text/plain',
'vrml' => 'model/vrml',
'vxml' => 'application/voicexml+xml',
'webm' => 'video/webm',
'webp' => 'image/webp',
'wrl' => 'model/vrml',
'xht' => 'application/xhtml+xml',
'xhtml' => 'application/xhtml+xml',
'xml' => 'application/xml',
'xsl' => 'application/xml',
'xslt' => 'application/xslt+xml',
'xul' => 'application/vnd.mozilla.xul+xml',
);
}

View File

@ -0,0 +1,54 @@
<?php
namespace OSS\Core;
/**
* Class OssException
*
* OssClient在使用的时候所抛出的异常用户在使用OssClient的时候要Try住相关代码
* try的Exception应该是OssException其中会得到相关异常原因
*
* @package OSS\Core
*/
class OssException extends \Exception
{
private $details = array();
function __construct($details)
{
if (is_array($details)) {
$message = $details['code'] . ': ' . $details['message']
. ' RequestId: ' . $details['request-id'];
parent::__construct($message);
$this->details = $details;
} else {
$message = $details;
parent::__construct($message);
}
}
public function getHTTPStatus()
{
return isset($this->details['status']) ? $this->details['status'] : '';
}
public function getRequestId()
{
return isset($this->details['request-id']) ? $this->details['request-id'] : '';
}
public function getErrorCode()
{
return isset($this->details['code']) ? $this->details['code'] : '';
}
public function getErrorMessage()
{
return isset($this->details['message']) ? $this->details['message'] : '';
}
public function getDetails()
{
return isset($this->details['body']) ? $this->details['body'] : '';
}
}

View File

@ -0,0 +1,461 @@
<?php
namespace OSS\Core;
/**
* Class OssUtil
*
* Oss工具类主要供OssClient使用用户也可以使用本类进行返回结果的格式化
*
* @package OSS
*/
class OssUtil
{
const OSS_CONTENT = 'content';
const OSS_LENGTH = 'length';
const OSS_HEADERS = 'headers';
const OSS_MAX_OBJECT_GROUP_VALUE = 1000;
const OSS_MAX_PART_SIZE = 5368709120; // 5GB
const OSS_MID_PART_SIZE = 10485760; // 10MB
const OSS_MIN_PART_SIZE = 102400; // 100KB
/**
* 生成query params
*
* @param array $options 关联数组
* @return string 返回诸如 key1=value1&key2=value2
*/
public static function toQueryString($options = array())
{
$temp = array();
uksort($options, 'strnatcasecmp');
foreach ($options as $key => $value) {
if (is_string($key) && !is_array($value)) {
$temp[] = rawurlencode($key) . '=' . rawurlencode($value);
}
}
return implode('&', $temp);
}
/**
* 转义字符替换
*
* @param string $subject
* @return string
*/
public static function sReplace($subject)
{
$search = array('<', '>', '&', '\'', '"');
$replace = array('&lt;', '&gt;', '&amp;', '&apos;', '&quot;');
return str_replace($search, $replace, $subject);
}
/**
* 检查是否是中文编码
*
* @param $str
* @return int
*/
public static function chkChinese($str)
{
return preg_match('/[\x80-\xff]./', $str);
}
/**
* 检测是否GB2312编码
*
* @param string $str
* @return boolean false UTF-8编码 TRUE GB2312编码
*/
public static function isGb2312($str)
{
for ($i = 0; $i < strlen($str); $i++) {
$v = ord($str[$i]);
if ($v > 127) {
if (($v >= 228) && ($v <= 233)) {
if (($i + 2) >= (strlen($str) - 1)) return true; // not enough characters
$v1 = ord($str[$i + 1]);
$v2 = ord($str[$i + 2]);
if (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191))
return false;
else
return true;
}
}
}
return false;
}
/**
* 检测是否GBK编码
*
* @param string $str
* @param boolean $gbk
* @return boolean
*/
public static function checkChar($str, $gbk = true)
{
for ($i = 0; $i < strlen($str); $i++) {
$v = ord($str[$i]);
if ($v > 127) {
if (($v >= 228) && ($v <= 233)) {
if (($i + 2) >= (strlen($str) - 1)) return $gbk ? true : FALSE; // not enough characters
$v1 = ord($str[$i + 1]);
$v2 = ord($str[$i + 2]);
if ($gbk) {
return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? FALSE : TRUE;//GBK
} else {
return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? TRUE : FALSE;
}
}
}
}
return $gbk ? TRUE : FALSE;
}
/**
* 检验bucket名称是否合法
* bucket的命名规范
* 1. 只能包括小写字母,数字
* 2. 必须以小写字母或者数字开头
* 3. 长度必须在3-63字节之间
*
* @param string $bucket Bucket名称
* @return boolean
*/
public static function validateBucket($bucket)
{
$pattern = '/^[a-z0-9][a-z0-9-]{2,62}$/';
if (!preg_match($pattern, $bucket)) {
return false;
}
return true;
}
/**
* 检验object名称是否合法
* object命名规范:
* 1. 规则长度必须在1-1023字节之间
* 2. 使用UTF-8编码
* 3. 不能以 "/" "\\"开头
*
* @param string $object Object名称
* @return boolean
*/
public static function validateObject($object)
{
$pattern = '/^.{1,1023}$/';
if (empty($object) || !preg_match($pattern, $object) ||
self::startsWith($object, '/') || self::startsWith($object, '\\')
) {
return false;
}
return true;
}
/**
* 判断字符串$str是不是以$findMe开始
*
* @param string $str
* @param string $findMe
* @return bool
*/
public static function startsWith($str, $findMe)
{
if (strpos($str, $findMe) === 0) {
return true;
} else {
return false;
}
}
/**
* 生成createBucketXmlBody接口的xml消息
*
* @param string $storageClass
* @return string
*/
public static function createBucketXmlBody($storageClass)
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration></CreateBucketConfiguration>');
$xml->addChild('StorageClass', $storageClass);
return $xml->asXML();
}
/**
* 检验$options
*
* @param array $options
* @throws OssException
* @return boolean
*/
public static function validateOptions($options)
{
//$options
if ($options != NULL && !is_array($options)) {
throw new OssException ($options . ':' . 'option must be array');
}
}
/**
* 检查上传文件的内容是否合法
*
* @param $content string
* @throws OssException
*/
public static function validateContent($content)
{
if (empty($content)) {
throw new OssException("http body content is invalid");
}
}
/**
* 校验BUCKET/OBJECT/OBJECT GROUP是否为空
*
* @param string $name
* @param string $errMsg
* @throws OssException
* @return void
*/
public static function throwOssExceptionWithMessageIfEmpty($name, $errMsg)
{
if (empty($name)) {
throw new OssException($errMsg);
}
}
/**
* 仅供测试使用的接口,请勿使用
*
* @param $filename
* @param $size
*/
public static function generateFile($filename, $size)
{
if (file_exists($filename) && $size == filesize($filename)) {
echo $filename . " already exists, no need to create again. ";
return;
}
$part_size = 1 * 1024 * 1024;
$fp = fopen($filename, "w");
$characters = <<<BBB
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
BBB;
$charactersLength = strlen($characters);
if ($fp) {
while ($size > 0) {
if ($size < $part_size) {
$write_size = $size;
} else {
$write_size = $part_size;
}
$size -= $write_size;
$a = $characters[rand(0, $charactersLength - 1)];
$content = str_repeat($a, $write_size);
$flag = fwrite($fp, $content);
if (!$flag) {
echo "write to " . $filename . " failed. <br>";
break;
}
}
} else {
echo "open " . $filename . " failed. <br>";
}
fclose($fp);
}
/**
* 得到文件的md5编码
*
* @param $filename
* @param $from_pos
* @param $to_pos
* @return string
*/
public static function getMd5SumForFile($filename, $from_pos, $to_pos)
{
$content_md5 = "";
if (($to_pos - $from_pos) > self::OSS_MAX_PART_SIZE) {
return $content_md5;
}
$filesize = filesize($filename);
if ($from_pos >= $filesize || $to_pos >= $filesize || $from_pos < 0 || $to_pos < 0) {
return $content_md5;
}
$total_length = $to_pos - $from_pos + 1;
$buffer = 8192;
$left_length = $total_length;
if (!file_exists($filename)) {
return $content_md5;
}
if (false === $fh = fopen($filename, 'rb')) {
return $content_md5;
}
fseek($fh, $from_pos);
$data = '';
while (!feof($fh)) {
if ($left_length >= $buffer) {
$read_length = $buffer;
} else {
$read_length = $left_length;
}
if ($read_length <= 0) {
break;
} else {
$data .= fread($fh, $read_length);
$left_length = $left_length - $read_length;
}
}
fclose($fh);
$content_md5 = base64_encode(md5($data, true));
return $content_md5;
}
/**
* 检测是否windows系统因为windows系统默认编码为GBK
*
* @return bool
*/
public static function isWin()
{
return strtoupper(substr(PHP_OS, 0, 3)) == "WIN";
}
/**
* 主要是由于windows系统编码是gbk遇到中文时候如果不进行转换处理会出现找不到文件的问题
*
* @param $file_path
* @return string
*/
public static function encodePath($file_path)
{
if (self::chkChinese($file_path) && self::isWin()) {
$file_path = iconv('utf-8', 'gbk', $file_path);
}
return $file_path;
}
/**
* 判断用户输入的endpoint是否是 xxx.xxx.xxx.xxx:port 或者 xxx.xxx.xxx.xxx的ip格式
*
* @param string $endpoint 需要做判断的endpoint
* @return boolean
*/
public static function isIPFormat($endpoint)
{
$ip_array = explode(":", $endpoint);
$hostname = $ip_array[0];
$ret = filter_var($hostname, FILTER_VALIDATE_IP);
if (!$ret) {
return false;
} else {
return true;
}
}
/**
* 生成DeleteMultiObjects接口的xml消息
*
* @param string[] $objects
* @param bool $quiet
* @return string
*/
public static function createDeleteObjectsXmlBody($objects, $quiet)
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><Delete></Delete>');
$xml->addChild('Quiet', $quiet);
foreach ($objects as $object) {
$sub_object = $xml->addChild('Object');
$object = OssUtil::sReplace($object);
$sub_object->addChild('Key', $object);
}
return $xml->asXML();
}
/**
* 生成CompleteMultipartUpload接口的xml消息
*
* @param array[] $listParts
* @return string
*/
public static function createCompleteMultipartUploadXmlBody($listParts)
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload></CompleteMultipartUpload>');
foreach ($listParts as $node) {
$part = $xml->addChild('Part');
$part->addChild('PartNumber', $node['PartNumber']);
$part->addChild('ETag', $node['ETag']);
}
return $xml->asXML();
}
/**
* 读取目录
*
* @param string $dir
* @param string $exclude
* @param bool $recursive
* @return string[]
*/
public static function readDir($dir, $exclude = ".|..|.svn|.git", $recursive = false)
{
$file_list_array = array();
$base_path = $dir;
$exclude_array = explode("|", $exclude);
$exclude_array = array_unique(array_merge($exclude_array, array('.', '..')));
if ($recursive) {
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir)) as $new_file) {
if ($new_file->isDir()) continue;
$object = str_replace($base_path, '', $new_file);
if (!in_array(strtolower($object), $exclude_array)) {
$object = ltrim($object, '/');
if (is_file($new_file)) {
$key = md5($new_file . $object, false);
$file_list_array[$key] = array('path' => $new_file, 'file' => $object,);
}
}
}
} else if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if (!in_array(strtolower($file), $exclude_array)) {
$new_file = $dir . '/' . $file;
$object = $file;
$object = ltrim($object, '/');
if (is_file($new_file)) {
$key = md5($new_file . $object, false);
$file_list_array[$key] = array('path' => $new_file, 'file' => $object,);
}
}
}
closedir($handle);
}
return $file_list_array;
}
/**
* Decode key based on the encoding type
*
* @param string $key
* @param string $encoding
* @return string
*/
public static function decodeKey($key, $encoding)
{
if ($encoding == "") {
return $key;
}
if ($encoding == "url") {
return rawurldecode($key);
} else {
throw new OssException("Unrecognized encoding type: " . $encoding);
}
}
}

View File

@ -0,0 +1,25 @@
Copyright (c) 2006-2010 Ryan Parman, Foleeo Inc., and contributors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Ryan Parman, Foleeo Inc. nor the names of its contributors may be used to
endorse or promote products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,896 @@
<?php
namespace OSS\Http;
/**
* Handles all HTTP requests using cURL and manages the responses.
*
* @version 2011.06.07
* @copyright 2006-2011 Ryan Parman
* @copyright 2006-2010 Foleeo Inc.
* @copyright 2010-2011 Amazon.com, Inc. or its affiliates.
* @copyright 2008-2011 Contributors
* @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
*/
class RequestCore
{
/**
* The URL being requested.
*/
public $request_url;
/**
* The headers being sent in the request.
*/
public $request_headers;
/**
* The raw response callback headers
*/
public $response_raw_headers;
/**
* Response body when error occurs
*/
public $response_error_body;
/**
*The hander of write file
*/
public $write_file_handle;
/**
* The body being sent in the request.
*/
public $request_body;
/**
* The response returned by the request.
*/
public $response;
/**
* The headers returned by the request.
*/
public $response_headers;
/**
* The body returned by the request.
*/
public $response_body;
/**
* The HTTP status code returned by the request.
*/
public $response_code;
/**
* Additional response data.
*/
public $response_info;
/**
* The method by which the request is being made.
*/
public $method;
/**
* Stores the proxy settings to use for the request.
*/
public $proxy = null;
/**
* The username to use for the request.
*/
public $username = null;
/**
* The password to use for the request.
*/
public $password = null;
/**
* Custom CURLOPT settings.
*/
public $curlopts = null;
/**
* The state of debug mode.
*/
public $debug_mode = false;
/**
* The default class to use for HTTP Requests (defaults to <RequestCore>).
*/
public $request_class = 'OSS\Http\RequestCore';
/**
* The default class to use for HTTP Responses (defaults to <ResponseCore>).
*/
public $response_class = 'OSS\Http\ResponseCore';
/**
* Default useragent string to use.
*/
public $useragent = 'RequestCore/1.4.3';
/**
* File to read from while streaming up.
*/
public $read_file = null;
/**
* The resource to read from while streaming up.
*/
public $read_stream = null;
/**
* The size of the stream to read from.
*/
public $read_stream_size = null;
/**
* The length already read from the stream.
*/
public $read_stream_read = 0;
/**
* File to write to while streaming down.
*/
public $write_file = null;
/**
* The resource to write to while streaming down.
*/
public $write_stream = null;
/**
* Stores the intended starting seek position.
*/
public $seek_position = null;
/**
* The location of the cacert.pem file to use.
*/
public $cacert_location = false;
/**
* The state of SSL certificate verification.
*/
public $ssl_verification = true;
/**
* The user-defined callback function to call when a stream is read from.
*/
public $registered_streaming_read_callback = null;
/**
* The user-defined callback function to call when a stream is written to.
*/
public $registered_streaming_write_callback = null;
/**
* 请求超时时间, 默认是5184000秒6天
*
* @var int
*/
public $timeout = 5184000;
/**
* 连接超时时间默认是10秒
*
* @var int
*/
public $connect_timeout = 10;
/*%******************************************************************************************%*/
// CONSTANTS
/**
* GET HTTP Method
*/
const HTTP_GET = 'GET';
/**
* POST HTTP Method
*/
const HTTP_POST = 'POST';
/**
* PUT HTTP Method
*/
const HTTP_PUT = 'PUT';
/**
* DELETE HTTP Method
*/
const HTTP_DELETE = 'DELETE';
/**
* HEAD HTTP Method
*/
const HTTP_HEAD = 'HEAD';
/*%******************************************************************************************%*/
// CONSTRUCTOR/DESTRUCTOR
/**
* Constructs a new instance of this class.
*
* @param string $url (Optional) The URL to request or service endpoint to query.
* @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
* @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
* @return $this A reference to the current instance.
*/
public function __construct($url = null, $proxy = null, $helpers = null)
{
// Set some default values.
$this->request_url = $url;
$this->method = self::HTTP_GET;
$this->request_headers = array();
$this->request_body = '';
// Set a new Request class if one was set.
if (isset($helpers['request']) && !empty($helpers['request'])) {
$this->request_class = $helpers['request'];
}
// Set a new Request class if one was set.
if (isset($helpers['response']) && !empty($helpers['response'])) {
$this->response_class = $helpers['response'];
}
if ($proxy) {
$this->set_proxy($proxy);
}
return $this;
}
/**
* Destructs the instance. Closes opened file handles.
*
* @return $this A reference to the current instance.
*/
public function __destruct()
{
if (isset($this->read_file) && isset($this->read_stream)) {
fclose($this->read_stream);
}
if (isset($this->write_file) && isset($this->write_stream)) {
fclose($this->write_stream);
}
return $this;
}
/*%******************************************************************************************%*/
// REQUEST METHODS
/**
* Sets the credentials to use for authentication.
*
* @param string $user (Required) The username to authenticate with.
* @param string $pass (Required) The password to authenticate with.
* @return $this A reference to the current instance.
*/
public function set_credentials($user, $pass)
{
$this->username = $user;
$this->password = $pass;
return $this;
}
/**
* Adds a custom HTTP header to the cURL request.
*
* @param string $key (Required) The custom HTTP header to set.
* @param mixed $value (Required) The value to assign to the custom HTTP header.
* @return $this A reference to the current instance.
*/
public function add_header($key, $value)
{
$this->request_headers[$key] = $value;
return $this;
}
/**
* Removes an HTTP header from the cURL request.
*
* @param string $key (Required) The custom HTTP header to set.
* @return $this A reference to the current instance.
*/
public function remove_header($key)
{
if (isset($this->request_headers[$key])) {
unset($this->request_headers[$key]);
}
return $this;
}
/**
* Set the method type for the request.
*
* @param string $method (Required) One of the following constants: <HTTP_GET>, <HTTP_POST>, <HTTP_PUT>, <HTTP_HEAD>, <HTTP_DELETE>.
* @return $this A reference to the current instance.
*/
public function set_method($method)
{
$this->method = strtoupper($method);
return $this;
}
/**
* Sets a custom useragent string for the class.
*
* @param string $ua (Required) The useragent string to use.
* @return $this A reference to the current instance.
*/
public function set_useragent($ua)
{
$this->useragent = $ua;
return $this;
}
/**
* Set the body to send in the request.
*
* @param string $body (Required) The textual content to send along in the body of the request.
* @return $this A reference to the current instance.
*/
public function set_body($body)
{
$this->request_body = $body;
return $this;
}
/**
* Set the URL to make the request to.
*
* @param string $url (Required) The URL to make the request to.
* @return $this A reference to the current instance.
*/
public function set_request_url($url)
{
$this->request_url = $url;
return $this;
}
/**
* Set additional CURLOPT settings. These will merge with the default settings, and override if
* there is a duplicate.
*
* @param array $curlopts (Optional) A set of key-value pairs that set `CURLOPT` options. These will merge with the existing CURLOPTs, and ones passed here will override the defaults. Keys should be the `CURLOPT_*` constants, not strings.
* @return $this A reference to the current instance.
*/
public function set_curlopts($curlopts)
{
$this->curlopts = $curlopts;
return $this;
}
/**
* Sets the length in bytes to read from the stream while streaming up.
*
* @param integer $size (Required) The length in bytes to read from the stream.
* @return $this A reference to the current instance.
*/
public function set_read_stream_size($size)
{
$this->read_stream_size = $size;
return $this;
}
/**
* Sets the resource to read from while streaming up. Reads the stream from its current position until
* EOF or `$size` bytes have been read. If `$size` is not given it will be determined by <php:fstat()> and
* <php:ftell()>.
*
* @param resource $resource (Required) The readable resource to read from.
* @param integer $size (Optional) The size of the stream to read.
* @return $this A reference to the current instance.
*/
public function set_read_stream($resource, $size = null)
{
if (!isset($size) || $size < 0) {
$stats = fstat($resource);
if ($stats && $stats['size'] >= 0) {
$position = ftell($resource);
if ($position !== false && $position >= 0) {
$size = $stats['size'] - $position;
}
}
}
$this->read_stream = $resource;
return $this->set_read_stream_size($size);
}
/**
* Sets the file to read from while streaming up.
*
* @param string $location (Required) The readable location to read from.
* @return $this A reference to the current instance.
*/
public function set_read_file($location)
{
$this->read_file = $location;
$read_file_handle = fopen($location, 'r');
return $this->set_read_stream($read_file_handle);
}
/**
* Sets the resource to write to while streaming down.
*
* @param resource $resource (Required) The writeable resource to write to.
* @return $this A reference to the current instance.
*/
public function set_write_stream($resource)
{
$this->write_stream = $resource;
return $this;
}
/**
* Sets the file to write to while streaming down.
*
* @param string $location (Required) The writeable location to write to.
* @return $this A reference to the current instance.
*/
public function set_write_file($location)
{
$this->write_file = $location;
}
/**
* Set the proxy to use for making requests.
*
* @param string $proxy (Required) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
* @return $this A reference to the current instance.
*/
public function set_proxy($proxy)
{
$proxy = parse_url($proxy);
$proxy['user'] = isset($proxy['user']) ? $proxy['user'] : null;
$proxy['pass'] = isset($proxy['pass']) ? $proxy['pass'] : null;
$proxy['port'] = isset($proxy['port']) ? $proxy['port'] : null;
$this->proxy = $proxy;
return $this;
}
/**
* Set the intended starting seek position.
*
* @param integer $position (Required) The byte-position of the stream to begin reading from.
* @return $this A reference to the current instance.
*/
public function set_seek_position($position)
{
$this->seek_position = isset($position) ? (integer)$position : null;
return $this;
}
/**
* A callback function that is invoked by cURL for streaming up.
*
* @param resource $curl_handle (Required) The cURL handle for the request.
* @param resource $header_content (Required) The header callback result.
* @return headers from a stream.
*/
public function streaming_header_callback($curl_handle, $header_content)
{
$code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
if (isset($this->write_file) && intval($code) / 100 == 2 && !isset($this->write_file_handle))
{
$this->write_file_handle = fopen($this->write_file, 'w');
$this->set_write_stream($this->write_file_handle);
}
$this->response_raw_headers .= $header_content;
return strlen($header_content);
}
/**
* Register a callback function to execute whenever a data stream is read from using
* <CFRequest::streaming_read_callback()>.
*
* The user-defined callback function should accept three arguments:
*
* <ul>
* <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
* <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
* <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
* </ul>
*
* @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
* <li>The name of a global function to execute, passed as a string.</li>
* <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
* <li>An anonymous function (PHP 5.3+).</li></ul>
* @return $this A reference to the current instance.
*/
public function register_streaming_read_callback($callback)
{
$this->registered_streaming_read_callback = $callback;
return $this;
}
/**
* Register a callback function to execute whenever a data stream is written to using
* <CFRequest::streaming_write_callback()>.
*
* The user-defined callback function should accept two arguments:
*
* <ul>
* <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
* <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
* </ul>
*
* @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
* <li>The name of a global function to execute, passed as a string.</li>
* <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
* <li>An anonymous function (PHP 5.3+).</li></ul>
* @return $this A reference to the current instance.
*/
public function register_streaming_write_callback($callback)
{
$this->registered_streaming_write_callback = $callback;
return $this;
}
/*%******************************************************************************************%*/
// PREPARE, SEND, AND PROCESS REQUEST
/**
* A callback function that is invoked by cURL for streaming up.
*
* @param resource $curl_handle (Required) The cURL handle for the request.
* @param resource $file_handle (Required) The open file handle resource.
* @param integer $length (Required) The maximum number of bytes to read.
* @return binary Binary data from a stream.
*/
public function streaming_read_callback($curl_handle, $file_handle, $length)
{
// Once we've sent as much as we're supposed to send...
if ($this->read_stream_read >= $this->read_stream_size) {
// Send EOF
return '';
}
// If we're at the beginning of an upload and need to seek...
if ($this->read_stream_read == 0 && isset($this->seek_position) && $this->seek_position !== ftell($this->read_stream)) {
if (fseek($this->read_stream, $this->seek_position) !== 0) {
throw new RequestCore_Exception('The stream does not support seeking and is either not at the requested position or the position is unknown.');
}
}
$read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
$this->read_stream_read += strlen($read);
$out = $read === false ? '' : $read;
// Execute callback function
if ($this->registered_streaming_read_callback) {
call_user_func($this->registered_streaming_read_callback, $curl_handle, $file_handle, $out);
}
return $out;
}
/**
* A callback function that is invoked by cURL for streaming down.
*
* @param resource $curl_handle (Required) The cURL handle for the request.
* @param binary $data (Required) The data to write.
* @return integer The number of bytes written.
*/
public function streaming_write_callback($curl_handle, $data)
{
$code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
if (intval($code) / 100 != 2)
{
$this->response_error_body .= $data;
return strlen($data);
}
$length = strlen($data);
$written_total = 0;
$written_last = 0;
while ($written_total < $length) {
$written_last = fwrite($this->write_stream, substr($data, $written_total));
if ($written_last === false) {
return $written_total;
}
$written_total += $written_last;
}
// Execute callback function
if ($this->registered_streaming_write_callback) {
call_user_func($this->registered_streaming_write_callback, $curl_handle, $written_total);
}
return $written_total;
}
/**
* Prepares and adds the details of the cURL request. This can be passed along to a <php:curl_multi_exec()>
* function.
*
* @return resource The handle for the cURL object.
*
*/
public function prep_request()
{
$curl_handle = curl_init();
// Set default options.
curl_setopt($curl_handle, CURLOPT_URL, $this->request_url);
curl_setopt($curl_handle, CURLOPT_FILETIME, true);
curl_setopt($curl_handle, CURLOPT_FRESH_CONNECT, false);
// curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
curl_setopt($curl_handle, CURLOPT_HEADER, true);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, $this->connect_timeout);
curl_setopt($curl_handle, CURLOPT_NOSIGNAL, true);
curl_setopt($curl_handle, CURLOPT_REFERER, $this->request_url);
curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
curl_setopt($curl_handle, CURLOPT_HEADERFUNCTION, array($this, 'streaming_header_callback'));
curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
// Verification of the SSL cert
if ($this->ssl_verification) {
curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
} else {
curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, false);
}
// chmod the file as 0755
if ($this->cacert_location === true) {
curl_setopt($curl_handle, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
} elseif (is_string($this->cacert_location)) {
curl_setopt($curl_handle, CURLOPT_CAINFO, $this->cacert_location);
}
// Debug mode
if ($this->debug_mode) {
curl_setopt($curl_handle, CURLOPT_VERBOSE, true);
}
// Handle open_basedir & safe mode
if (!ini_get('safe_mode') && !ini_get('open_basedir')) {
curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
}
// Enable a proxy connection if requested.
if ($this->proxy) {
$host = $this->proxy['host'];
$host .= ($this->proxy['port']) ? ':' . $this->proxy['port'] : '';
curl_setopt($curl_handle, CURLOPT_PROXY, $host);
if (isset($this->proxy['user']) && isset($this->proxy['pass'])) {
curl_setopt($curl_handle, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
}
}
// Set credentials for HTTP Basic/Digest Authentication.
if ($this->username && $this->password) {
curl_setopt($curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl_handle, CURLOPT_USERPWD, $this->username . ':' . $this->password);
}
// Handle the encoding if we can.
if (extension_loaded('zlib')) {
curl_setopt($curl_handle, CURLOPT_ENCODING, '');
}
// Process custom headers
if (isset($this->request_headers) && count($this->request_headers)) {
$temp_headers = array();
foreach ($this->request_headers as $k => $v) {
$temp_headers[] = $k . ': ' . $v;
}
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $temp_headers);
}
switch ($this->method) {
case self::HTTP_PUT:
//unset($this->read_stream);
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'PUT');
if (isset($this->read_stream)) {
if (!isset($this->read_stream_size) || $this->read_stream_size < 0) {
throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
}
curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
} else {
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
}
break;
case self::HTTP_POST:
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'POST');
if (isset($this->read_stream)) {
if (!isset($this->read_stream_size) || $this->read_stream_size < 0) {
throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
}
curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
} else {
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
}
break;
case self::HTTP_HEAD:
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, self::HTTP_HEAD);
curl_setopt($curl_handle, CURLOPT_NOBODY, 1);
break;
default: // Assumed GET
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $this->method);
if (isset($this->write_stream) || isset($this->write_file)) {
curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, array($this, 'streaming_write_callback'));
curl_setopt($curl_handle, CURLOPT_HEADER, false);
} else {
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
}
break;
}
// Merge in the CURLOPTs
if (isset($this->curlopts) && sizeof($this->curlopts) > 0) {
foreach ($this->curlopts as $k => $v) {
curl_setopt($curl_handle, $k, $v);
}
}
return $curl_handle;
}
/**
* Take the post-processed cURL data and break it down into useful header/body/info chunks. Uses the
* data stored in the `curl_handle` and `response` properties unless replacement data is passed in via
* parameters.
*
* @param resource $curl_handle (Optional) The reference to the already executed cURL request.
* @param string $response (Optional) The actual response content itself that needs to be parsed.
* @return ResponseCore A <ResponseCore> object containing a parsed HTTP response.
*/
public function process_response($curl_handle = null, $response = null)
{
// Accept a custom one if it's passed.
if ($curl_handle && $response) {
$this->response = $response;
}
// As long as this came back as a valid resource...
if (is_resource($curl_handle)) {
// Determine what's what.
$header_size = curl_getinfo($curl_handle, CURLINFO_HEADER_SIZE);
$this->response_headers = substr($this->response, 0, $header_size);
$this->response_body = substr($this->response, $header_size);
$this->response_code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
$this->response_info = curl_getinfo($curl_handle);
if (intval($this->response_code) / 100 != 2 && isset($this->write_file))
{
$this->response_headers = $this->response_raw_headers;
$this->response_body = $this->response_error_body;
}
// Parse out the headers
$this->response_headers = explode("\r\n\r\n", trim($this->response_headers));
$this->response_headers = array_pop($this->response_headers);
$this->response_headers = explode("\r\n", $this->response_headers);
array_shift($this->response_headers);
// Loop through and split up the headers.
$header_assoc = array();
foreach ($this->response_headers as $header) {
$kv = explode(': ', $header);
$header_assoc[strtolower($kv[0])] = isset($kv[1]) ? $kv[1] : '';
}
// Reset the headers to the appropriate property.
$this->response_headers = $header_assoc;
$this->response_headers['info'] = $this->response_info;
$this->response_headers['info']['method'] = $this->method;
if ($curl_handle && $response) {
return new ResponseCore($this->response_headers, $this->response_body, $this->response_code);
}
}
// Return false
return false;
}
/**
* Sends the request, calling necessary utility functions to update built-in properties.
*
* @param boolean $parse (Optional) Whether to parse the response with ResponseCore or not.
* @return string The resulting unparsed data from the request.
*/
public function send_request($parse = false)
{
set_time_limit(0);
$curl_handle = $this->prep_request();
$this->response = curl_exec($curl_handle);
if ($this->response === false) {
throw new RequestCore_Exception('cURL resource: ' . (string)$curl_handle . '; cURL error: ' . curl_error($curl_handle) . ' (' . curl_errno($curl_handle) . ')');
}
$parsed_response = $this->process_response($curl_handle, $this->response);
curl_close($curl_handle);
if ($parse) {
return $parsed_response;
}
return $this->response;
}
/*%******************************************************************************************%*/
// RESPONSE METHODS
/**
* Get the HTTP response headers from the request.
*
* @param string $header (Optional) A specific header value to return. Defaults to all headers.
* @return string|array All or selected header values.
*/
public function get_response_header($header = null)
{
if ($header) {
return $this->response_headers[strtolower($header)];
}
return $this->response_headers;
}
/**
* Get the HTTP response body from the request.
*
* @return string The response body.
*/
public function get_response_body()
{
return $this->response_body;
}
/**
* Get the HTTP response code from the request.
*
* @return string The HTTP response code.
*/
public function get_response_code()
{
return $this->response_code;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace OSS\Http;
class RequestCore_Exception extends \Exception
{
}

View File

@ -0,0 +1,56 @@
<?php
namespace OSS\Http;
/**
* Container for all response-related methods.
*/
class ResponseCore
{
/**
* Stores the HTTP header information.
*/
public $header;
/**
* Stores the SimpleXML response.
*/
public $body;
/**
* Stores the HTTP response code.
*/
public $status;
/**
* Constructs a new instance of this class.
*
* @param array $header (Required) Associative array of HTTP headers (typically returned by <RequestCore::get_response_header()>).
* @param string $body (Required) XML-formatted response from AWS.
* @param integer $status (Optional) HTTP response status code from the request.
* @return Mixed Contains an <php:array> `header` property (HTTP headers as an associative array), a <php:SimpleXMLElement> or <php:string> `body` property, and an <php:integer> `status` code.
*/
public function __construct($header, $body, $status = null)
{
$this->header = $header;
$this->body = $body;
$this->status = $status;
return $this;
}
/**
* Did we receive the status code we expected?
*
* @param integer|array $codes (Optional) The status code(s) to expect. Pass an <php:integer> for a single acceptable value, or an <php:array> of integers for multiple acceptable values.
* @return boolean Whether we received the expected status code or not.
*/
public function isOK($codes = array(200, 201, 204, 206))
{
if (is_array($codes)) {
return in_array($this->status, $codes);
}
return $this->status === $codes;
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace OSS\Model;
/**
* Bucket信息ListBuckets接口返回数据
*
* Class BucketInfo
* @package OSS\Model
*/
class BucketInfo
{
/**
* BucketInfo constructor.
*
* @param string $location
* @param string $name
* @param string $createDate
*/
public function __construct($location, $name, $createDate)
{
$this->location = $location;
$this->name = $name;
$this->createDate = $createDate;
}
/**
* 得到bucket所在的region
*
* @return string
*/
public function getLocation()
{
return $this->location;
}
/**
* 得到bucket的名称
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* 得到bucket的创建时间
*
* @return string
*/
public function getCreateDate()
{
return $this->createDate;
}
/**
* bucket所在的region
*
* @var string
*/
private $location;
/**
* bucket的名称
*
* @var string
*/
private $name;
/**
* bucket的创建事件
*
* @var string
*/
private $createDate;
}

View File

@ -0,0 +1,39 @@
<?php
namespace OSS\Model;
/**
* Class BucketListInfo
*
* ListBuckets接口返回的数据类型
*
* @package OSS\Model
*/
class BucketListInfo
{
/**
* BucketListInfo constructor.
* @param array $bucketList
*/
public function __construct(array $bucketList)
{
$this->bucketList = $bucketList;
}
/**
* 得到BucketInfo列表
*
* @return BucketInfo[]
*/
public function getBucketList()
{
return $this->bucketList;
}
/**
* BucketInfo信息列表
*
* @var array
*/
private $bucketList = array();
}

View File

@ -0,0 +1,99 @@
<?php
namespace OSS\Model;
use OSS\Core\OssException;
/**
* Class CnameConfig
* @package OSS\Model
*
* TODO: fix link
* @link http://help.aliyun.com/document_detail/oss/api-reference/cors/PutBucketcors.html
*/
class CnameConfig implements XmlConfig
{
public function __construct()
{
$this->cnameList = array();
}
/**
* @return array
* @example
* array(2) {
* [0]=>
* array(3) {
* ["Domain"]=>
* string(11) "www.foo.com"
* ["Status"]=>
* string(7) "enabled"
* ["LastModified"]=>
* string(8) "20150101"
* }
* [1]=>
* array(3) {
* ["Domain"]=>
* string(7) "bar.com"
* ["Status"]=>
* string(8) "disabled"
* ["LastModified"]=>
* string(8) "20160101"
* }
* }
*/
public function getCnames()
{
return $this->cnameList;
}
public function addCname($cname)
{
if (count($this->cnameList) >= self::OSS_MAX_RULES) {
throw new OssException(
"num of cname in the config exceeds self::OSS_MAX_RULES: " . strval(self::OSS_MAX_RULES));
}
$this->cnameList[] = array('Domain' => $cname);
}
public function parseFromXml($strXml)
{
$xml = simplexml_load_string($strXml);
if (!isset($xml->Cname)) return;
foreach ($xml->Cname as $entry) {
$cname = array();
foreach ($entry as $key => $value) {
$cname[strval($key)] = strval($value);
}
$this->cnameList[] = $cname;
}
}
public function serializeToXml()
{
$strXml = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<BucketCnameConfiguration>
</BucketCnameConfiguration>
EOF;
$xml = new \SimpleXMLElement($strXml);
foreach ($this->cnameList as $cname) {
$node = $xml->addChild('Cname');
foreach ($cname as $key => $value) {
$node->addChild($key, $value);
}
}
return $xml->asXML();
}
public function __toString()
{
return $this->serializeToXml();
}
const OSS_MAX_RULES = 10;
private $cnameList = array();
}

View File

@ -0,0 +1,113 @@
<?php
namespace OSS\Model;
use OSS\Core\OssException;
/**
* Class CorsConfig
* @package OSS\Model
*
* @link http://help.aliyun.com/document_detail/oss/api-reference/cors/PutBucketcors.html
*/
class CorsConfig implements XmlConfig
{
/**
* CorsConfig constructor.
*/
public function __construct()
{
$this->rules = array();
}
/**
* 得到CorsRule列表
*
* @return CorsRule[]
*/
public function getRules()
{
return $this->rules;
}
/**
* 添加一条CorsRule
*
* @param CorsRule $rule
* @throws OssException
*/
public function addRule($rule)
{
if (count($this->rules) >= self::OSS_MAX_RULES) {
throw new OssException("num of rules in the config exceeds self::OSS_MAX_RULES: " . strval(self::OSS_MAX_RULES));
}
$this->rules[] = $rule;
}
/**
* 从xml数据中解析出CorsConfig
*
* @param string $strXml
* @throws OssException
* @return null
*/
public function parseFromXml($strXml)
{
$xml = simplexml_load_string($strXml);
if (!isset($xml->CORSRule)) return;
foreach ($xml->CORSRule as $rule) {
$corsRule = new CorsRule();
foreach ($rule as $key => $value) {
if ($key === self::OSS_CORS_ALLOWED_HEADER) {
$corsRule->addAllowedHeader(strval($value));
} elseif ($key === self::OSS_CORS_ALLOWED_METHOD) {
$corsRule->addAllowedMethod(strval($value));
} elseif ($key === self::OSS_CORS_ALLOWED_ORIGIN) {
$corsRule->addAllowedOrigin(strval($value));
} elseif ($key === self::OSS_CORS_EXPOSE_HEADER) {
$corsRule->addExposeHeader(strval($value));
} elseif ($key === self::OSS_CORS_MAX_AGE_SECONDS) {
$corsRule->setMaxAgeSeconds(strval($value));
}
}
$this->addRule($corsRule);
}
return;
}
/**
* 生成xml字符串
*
* @return string
*/
public function serializeToXml()
{
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><CORSConfiguration></CORSConfiguration>');
foreach ($this->rules as $rule) {
$xmlRule = $xml->addChild('CORSRule');
$rule->appendToXml($xmlRule);
}
return $xml->asXML();
}
public function __toString()
{
return $this->serializeToXml();
}
const OSS_CORS_ALLOWED_ORIGIN = 'AllowedOrigin';
const OSS_CORS_ALLOWED_METHOD = 'AllowedMethod';
const OSS_CORS_ALLOWED_HEADER = 'AllowedHeader';
const OSS_CORS_EXPOSE_HEADER = 'ExposeHeader';
const OSS_CORS_MAX_AGE_SECONDS = 'MaxAgeSeconds';
const OSS_MAX_RULES = 10;
/**
* orsRule列表
*
* @var CorsRule[]
*/
private $rules = array();
}

View File

@ -0,0 +1,150 @@
<?php
namespace OSS\Model;
use OSS\Core\OssException;
/**
* Class CorsRule
* @package OSS\Model
* @link http://help.aliyun.com/document_detail/oss/api-reference/cors/PutBucketcors.html
*/
class CorsRule
{
/**
* Rule中增加一条allowedOrigin
*
* @param string $allowedOrigin
*/
public function addAllowedOrigin($allowedOrigin)
{
if (!empty($allowedOrigin)) {
$this->allowedOrigins[] = $allowedOrigin;
}
}
/**
* Rule中增加一条allowedMethod
*
* @param string $allowedMethod
*/
public function addAllowedMethod($allowedMethod)
{
if (!empty($allowedMethod)) {
$this->allowedMethods[] = $allowedMethod;
}
}
/**
* Rule中增加一条allowedHeader
*
* @param string $allowedHeader
*/
public function addAllowedHeader($allowedHeader)
{
if (!empty($allowedHeader)) {
$this->allowedHeaders[] = $allowedHeader;
}
}
/**
* Rule中增加一条exposeHeader
*
* @param string $exposeHeader
*/
public function addExposeHeader($exposeHeader)
{
if (!empty($exposeHeader)) {
$this->exposeHeaders[] = $exposeHeader;
}
}
/**
* @return int
*/
public function getMaxAgeSeconds()
{
return $this->maxAgeSeconds;
}
/**
* @param int $maxAgeSeconds
*/
public function setMaxAgeSeconds($maxAgeSeconds)
{
$this->maxAgeSeconds = $maxAgeSeconds;
}
/**
* 得到AllowedHeaders列表
*
* @return string[]
*/
public function getAllowedHeaders()
{
return $this->allowedHeaders;
}
/**
* 得到AllowedOrigins列表
*
* @return string[]
*/
public function getAllowedOrigins()
{
return $this->allowedOrigins;
}
/**
* 得到AllowedMethods列表
*
* @return string[]
*/
public function getAllowedMethods()
{
return $this->allowedMethods;
}
/**
* 得到ExposeHeaders列表
*
* @return string[]
*/
public function getExposeHeaders()
{
return $this->exposeHeaders;
}
/**
* 根据提供的xmlRule 把this按照一定的规则插入到$xmlRule中
*
* @param \SimpleXMLElement $xmlRule
* @throws OssException
*/
public function appendToXml(&$xmlRule)
{
if (!isset($this->maxAgeSeconds)) {
throw new OssException("maxAgeSeconds is not set in the Rule");
}
foreach ($this->allowedOrigins as $allowedOrigin) {
$xmlRule->addChild(CorsConfig::OSS_CORS_ALLOWED_ORIGIN, $allowedOrigin);
}
foreach ($this->allowedMethods as $allowedMethod) {
$xmlRule->addChild(CorsConfig::OSS_CORS_ALLOWED_METHOD, $allowedMethod);
}
foreach ($this->allowedHeaders as $allowedHeader) {
$xmlRule->addChild(CorsConfig::OSS_CORS_ALLOWED_HEADER, $allowedHeader);
}
foreach ($this->exposeHeaders as $exposeHeader) {
$xmlRule->addChild(CorsConfig::OSS_CORS_EXPOSE_HEADER, $exposeHeader);
}
$xmlRule->addChild(CorsConfig::OSS_CORS_MAX_AGE_SECONDS, strval($this->maxAgeSeconds));
}
private $allowedHeaders = array();
private $allowedOrigins = array();
private $allowedMethods = array();
private $exposeHeaders = array();
private $maxAgeSeconds = null;
}

Some files were not shown because too many files have changed in this diff Show More