同福

【阿里云】OSS存储服务

介绍

认识OSS

阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。

它具有与平台无关的RESTful API接口,能够提供99.999999999%(11个9)的数据可靠性和99.95%的服务可用性。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

了解Bucket

首先我们要建立一个Bucket(桶),用来存放我们的文件。

一个Bucket会有一个独立的访问域名,一般情况下一个项目建立一个Bucket就可以了。

如果项目有多个资源域名,那么就需要为每个域名建立一个独立的Bucket了。

准备

建立Bucket

第一步

2.jpg

第二步

3.jpg

新建策略

进入RAM控制台

不知道如何进入RAM控制台?点击下面的网址进去就是了。(问我怎么找到的?各种百度,反正阿里云是不会告诉你的)

https://ram.console.aliyun.com/ 

2.jpg

创建策略

1.jpg

授权策略

2.jpg

接入代码

下载PHP代码

https://github.com/aliyun/aliyun-oss-php-sdk 

接入参数

AccessKeyId

用于获得阿里云服务授权的账号

AccessKeySecret

用于获得阿里云服务授权的密码

EndPoint

地域节点分三个类型

  • 外网访问:通过互联网访问 OSS 的地址

  • ECS 的经典网络访问(内网):经典网络下的 ECS 与 OSS 之间的内网访问地址,内网产生的流入流出流量均免费

  • ECS 的 VPC 网络访问(内网):VPC 网络下的 ECS 与 OSS 之间的内网访问地址,内网产生的流入流出流量均免费

建立目录结构

建立我们的基础目录结构,一般情况下会是这样的结构

images/
images/usericon/
images/products/
attachments/

我们可以通过后台手动建立这些基础目录结构

1.jpg

当然,这些初始化目录结构的工作也可以通过编写代码的方法完成!

文件上传

文件权限

  • 公共读写,完全公开访问权限,任何人都可以操作。(太危险了,谁会开这种权限??)

  • 公共读,公开只读权限,任何人都可以读取文件,但不能改写。

  • 私有,读写均不公开。(这有什么用?网盘。。。)

  • 继承Bucket,继承Bucket的权限设定。(默认)

PHP SDK包结构

samples
src
---- OSS
-------- Core
-------- Http
-------- Model
-------- Result
-------- OssClient.php
tests

简易操作对象代码

  • 复制 OSS 目录到自己的项目下

  • 复制以下代码到 OSS/OssClient.php 文件的最下面

function AliCloudOSSAutoload($class)
{
    $path = preg_replace('/^OSS/', '', str_replace('\\', DIRECTORY_SEPARATOR, $class));
    $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
    if (file_exists($file)) {
        include_once $file;
    }
}
spl_autoload_register('OSS\\AliCloudOSSAutoload');

class OssDemo{
	
	private $ossArgv;
	private $ossActObj;
	
	public function __construct(){
		$this->ossArgv = array(
			'akId'=>"......",
			'akSecret'=>"......",
			'akEndPoint'=>"oss-cn-qingdao.aliyuncs.com",
			'bucket'=>"demo",
		); 
		$this->ossActObj = new OssClient($this->ossArgv['akId'], $this->ossArgv['akSecret'], $this->ossArgv['akEndPoint']);
	}
	
	private function _reconnect(){
		$this->ossActObj = new OssClient($this->ossArgv['akId'], $this->ossArgv['akSecret'], $this->ossArgv['akEndPoint']);
		sleep(1);
	}
	
	public function uploadFile($object, $file){
		try{
			$ret = $this->ossActObj->uploadFile($this->ossArgv['bucket'], $object, $file, array(
				OssClient::OSS_HEADERS => array(
					OssClient::OSS_OBJECT_ACL => OssClient::OSS_ACL_TYPE_PUBLIC_READ 
				)
			));
		}
		catch (OssException $e){
			$this->_reconnect();
			return $this->uploadFile($object, $file);
		}
		return $ret;
	}
	
	public function deleteFile($object){
		try{
			$ret = $this->ossActObj->deleteObject($this->ossArgv['bucket'], $object);
		}
		catch (OssException $e){
			$this->_reconnect();
			return $this->deleteFile($object);
		}
		return $ret;
	}
	
	public function getFile($object){
		try{
			$ret = $this->ossActObj->getObject($this->ossArgv['bucket'], $object);
		}
		catch (OssException $e){
			$this->_reconnect();
			return $this->getFile($object);
		}
		return $ret;
	}
	
	public function fileExists($object){
		try{
			$ret = $this->ossActObj->doesObjectExist($this->ossArgv['bucket'], $object);
		}
		catch (OssException $e){
			$this->_reconnect();
			return $this->fileExists($object);
		}
		return $ret;
	}
	
	public function putSymbol($symlink, $targetObject){
		try{
			$ret = $this->ossActObj->putSymlink($this->ossArgv['bucket'], $symlink, $targetObject, array(
				OssClient::OSS_HEADERS => array(
					OssClient::OSS_OBJECT_ACL => OssClient::OSS_ACL_TYPE_PUBLIC_READ 
				)
			));
		}
		catch (OssException $e){
			$this->_reconnect();
			return $this->putSymbol($symlink, $targetObject);
		}
		return $ret;
	}
	
	public function deleteDir($object){
		$prefix = $object;
		if(!preg_match("/\/$/", $prefix)) $prefix .= '/';
		$delimiter = '/';
		$nextMarker = '';
		$maxkeys = 1000;
		$options = array(
			'delimiter' => $delimiter,
			'prefix' => $prefix,
			'max-keys' => $maxkeys,
			'marker' => $nextMarker,
		);
		try{
			$listObjectInfo = $this->ossActObj->listObjects($this->ossArgv['bucket'], $options);
		}
		catch (OssException $e){
			$this->_reconnect();
			return $this->deleteDir($object);
		}
		$objs = $listObjectInfo->getObjectList();
		foreach ($objs as $obj){
			$this->deleteFile($obj->getKey());
		}
		$prefixs = $listObjectInfo->getPrefixList();
		foreach ($prefixs as $obj){
			$this->deleteDir($obj->getPrefix());
		}
		$this->deleteFile($object);
		return true;
	}
}
  • 在项目内包含 OSS/OssClient.php 文件,就可以通过对象 OssDemo 实现业务逻辑了

上传文件代码

use OSS\OssDemo;

$myOSSDemoObj = new OssDemo();

$ret = $myOSSDemoObj->uploadFile("images/a.jpg", "D:/a.jpg");

var_dump($ret);

文件删除

删除文件代码

use OSS\OssDemo;

$myOSSDemoObj = new OssDemo();

$ret = $myOSSDemoObj->deleteFile("images/a.jpg");

var_dump($ret);

文件下载

下载文件代码

use OSS\OssDemo;

$myOSSDemoObj = new OssDemo();

$ret = file_put_contents("D:/a.jpg", $myOSSDemoObj->getFile("images/a.jpg"));

var_dump($ret);

文件是否存在

检查文件是否存在

use OSS\OssDemo;

$myOSSDemoObj = new OssDemo();

$ret = $myOSSDemoObj->fileExists("images/a.jpg");

var_dump($ret);

创建符号链接

创建符号链接

use OSS\OssDemo;

$myOSSDemoObj = new OssDemo();

$ret = $myOSSDemoObj->putSymbol("images/a_symbol.jpg", "images/a.jpg");

var_dump($ret);

可以通过 fileExists 检查符号链接是否存在!

删除目录

删除整个目录

因为OSS服务本身是没有“目录”概念的,因此,我们采用递归的办法删除整个目录。

use OSS\OssDemo;

$myOSSDemoObj = new OssDemo();

$ret = $myOSSDemoObj->deleteDir("images/icon/");

var_dump($ret);

对接项目

准备工作

首先,我们需要将我们的资源域名独立出来,如果您的项目只有一个域名那只能使用OSS默认域名了。

一般情况下使用 img.yourdomain.com 或者 res.yourdomain.com。

域名选好了不要做 A记录 解析,直接 CNAME 到OSS域名即可。OSS域名就是 [bucket].[endpoint] 格式,例如:demo.oss-cn-qingdao.aliyuncs.com。

对接

对接说白了,就是把自己的上传代码改成OSS上传。

一般情况下,我们可以选择用JS上传或者PHP上传,我这里推荐如果是小文件还是选择PHP上传比较好,如果是大文件再考虑使用JS长传。

无论是JS还是PHP阿里云都提供了SDK包,我们可以下载使用。

总结

这样我们就可以完成和OSS的对接了!