Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加使用签名URL进行临时授权,支持生成私有bucket访问地址 #53

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "jacobcyl/ali-oss-storage",
"name": "summergeorge/ali-oss-storage",
"description": "aliyun oss filesystem storage for laravel 5+",
"keywords": ["aliyun", "oss", "laravel", "filesystems", "storage"],
"homepage": "http://jacobcyl.github.io/Aliyun-oss-storage/",
"homepage": "https://github.com/summergeorge/Aliyun-oss-storage",
"license": "MIT",
"authors": [
{
"name": "jacobcyl",
"email": "cyl.jacob@gmail.com"
"name": "summergeorge",
"email": "qihao201net@126.com"
}
],
"require": {
Expand Down
34 changes: 30 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
> 如果本项目对您有帮助且愿意花时间一起维护,欢迎提交PR,我将每个月做一次PR合并。

> 如果您想和我一起维护,欢迎发邮件给我,我将把您加为项目协作者。
# Aliyun-oss-storage for Laravel 5+
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/summergeorge/Aliyun-oss-storage/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/summergeorge/Aliyun-oss-storage/?branch=master)
[![Build Status](https://scrutinizer-ci.com/g/summergeorge/Aliyun-oss-storage/badges/build.png?b=master)](https://scrutinizer-ci.com/g/summergeorge/Aliyun-oss-storage/build-status/master)
[![Latest Stable Version](https://poser.pugx.org/summergeorge/ali-oss-storage/v/stable)](https://packagist.org/packages/summergeorge/ali-oss-storage)
[![Total Downloads](https://poser.pugx.org/summergeorge/ali-oss-storage/downloads)](https://packagist.org/packages/summergeorge/ali-oss-storage)
[![Latest Unstable Version](https://poser.pugx.org/summergeorge/ali-oss-storage/v/unstable)](https://packagist.org/packages/summergeorge/ali-oss-storage)
[![License](https://poser.pugx.org/summergeorge/ali-oss-storage/license)](https://packagist.org/packages/summergeorge/ali-oss-storage)

---

Aliyun oss filesystem storage adapter for laravel 5. You can use Aliyun OSS just like laravel Storage as usual.
借鉴了一些优秀的代码,综合各方,同时做了更多优化,将会添加更多完善的接口和插件,打造Laravel最好的OSS Storage扩展


## Inspired By
- [thephpleague/flysystem-aws-s3-v2](https://github.com/thephpleague/flysystem-aws-s3-v2)
- [apollopy/flysystem-aliyun-oss](https://github.com/apollopy/flysystem-aliyun-oss)
- [jacobcyl/Aliyun-oss-storage](https://github.com/jacobcyl/Aliyun-oss-storage)

## Require
- Laravel 5+
- cURL extension

##Installation
之前 fork 的 [jacobcyl/Aliyun-oss-storage](https://github.com/jacobcyl/Aliyun-oss-storage) ,自2.1.1版本开始,增加新功能,更改 composer 包名称为:`summergeorge/ali-oss-storage`

## Installation
In order to install AliOSS-storage, just add

"jacobcyl/ali-oss-storage": "^2.1"
"summergeorge/ali-oss-storage": "^2.2"

to your composer.json. Then run `composer install` or `composer update`.
Or you can simply run below command to install:

"composer require jacobcyl/ali-oss-storage:^2.1"
"composer require summergeorge/ali-oss-storage:^2.2"

Then in your `config/app.php` add this line to providers array:
```php
Expand All @@ -34,7 +51,7 @@ Add the following in app/filesystems.php:
'access_key' => '<Your Aliyun OSS AccessKeySecret>',
'bucket' => '<OSS bucket name>',
'endpoint'     => '<the endpoint of OSS, E.g: oss-cn-hangzhou.aliyuncs.com | custom domain, E.g:img.abc.com>', // OSS 外网节点或自定义外部域名
           //'endpoint_internal' => '<internal endpoint [OSS内网节点] 如:oss-cn-shenzhen-internal.aliyuncs.com>', // v2.0.4 新增配置属性,如果为空,则默认使用 endpoint 配置(由于内网上传有点小问题未解决,请大家暂时不要使用内网节点上传,正在与阿里技术沟通中)
           'endpoint_internal' => '<internal endpoint [OSS内网节点] 如:oss-cn-shenzhen-internal.aliyuncs.com>', // v2.2.1 新增配置属性,如果为空,则默认使用 endpoint 配置
'cdnDomain'     => '<CDN domain, cdn域名>', // 如果isCName为true, getUrl会判断cdnDomain是否设定来决定返回的url,如果cdnDomain未设置,则使用endpoint来生成url,否则使用cdn
'ssl'           => <true|false> // true to use 'https://' and false to use 'http://'. default is false,
'isCName'       => <true|false> // 是否使用自定义域名,true: 则Storage.url()会使用自定义的cdn或域名生成文件url, false: 则使用外部节点生成url
Expand Down Expand Up @@ -96,6 +113,15 @@ Storage::deleteDirectory($directory); // Recursively delete a directory.It will
Storage::putRemoteFile('target/path/to/file/jacob.jpg', 'http://example.com/jacob.jpg'); //upload remote file to storage by remote url
// new function for v2.0.1 version
Storage::url('path/to/img.jpg') // get the file url
// new function for v2.1.1 version
Storage::signUrl('path/to/img.jpg',$timeout) //(请使用新的temporaryUrl方法) get the file url with signature,default timeout = 600
// new function for v2.1.4 version
Storage::temporaryUrl('path/to/img.jpg',$timeout) // get the file url with signature,default timeout = 600

// new function for v2.1.2 version
// 阿里云 oss 帮助文档:https://help.aliyun.com/document_detail/44688.html?spm=a2c4g.11186623.6.1199.40572e934MoHWu
// getProcessUrl(图片在 oss 中的路径,操作名称(例如:resize),参数(key => value 形式的数组));
Storage::getProcessUrl('path/to/img.jpg','resize', ['m' => 'fixed','h' => '100','w' => '100']) // picture processing,处理图片,支持 oss 图片处理的功能
```

## Documentation
Expand Down
51 changes: 41 additions & 10 deletions src/AliOssAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

namespace Jacobcyl\AliOSS;

use Dingo\Api\Contract\Transformer\Adapter;
use Illuminate\Support\Arr;
use League\Flysystem\Adapter\AbstractAdapter;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
use League\Flysystem\Util;
use OSS\Core\OssException;
use OSS\OssClient;
use Log;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
use Illuminate\Contracts\Filesystem\FileNotFoundException;

class AliOssAdapter extends AbstractAdapter
{
Expand Down Expand Up @@ -67,7 +67,7 @@ class AliOssAdapter extends AbstractAdapter
protected $bucket;

protected $endPoint;

protected $cdnDomain;

protected $ssl;
Expand Down Expand Up @@ -449,12 +449,16 @@ public function read($path)
public function readStream($path)
{
$result = $this->readObject($path);
$result['stream'] = $result['raw_contents'];
if (is_resource($result['raw_contents'])) {
$result['stream'] = $result['raw_contents'];
$result['raw_contents']->detachStream();
} else {
$result['stream'] = fopen('php://temp', 'r+');
fwrite($result['stream'], $result['raw_contents']);
}
rewind($result['stream']);
// Ensure the EntityBody object destruction doesn't close the stream
$result['raw_contents']->detachStream();
unset($result['raw_contents']);

return $result;
}

Expand Down Expand Up @@ -549,7 +553,7 @@ public function getVisibility($path)
$this->logErr(__FUNCTION__, $e);
return false;
}

if ($acl == OssClient::OSS_ACL_TYPE_PUBLIC_READ ){
$res['visibility'] = AdapterInterface::VISIBILITY_PUBLIC;
}else{
Expand All @@ -567,10 +571,37 @@ public function getVisibility($path)
*/
public function getUrl( $path )
{
if (!$this->has($path)) throw new FileNotFoundException($filePath.' not found');
if (!$this->has($path)) throw new FileNotFoundException($path.' not found');
return ( $this->ssl ? 'https://' : 'http://' ) . ( $this->isCname ? ( $this->cdnDomain == '' ? $this->endPoint : $this->cdnDomain ) : $this->bucket . '.' . $this->endPoint ) . '/' . ltrim($path, '/');
}


/**
* @param $path
* @param $expire
* @param $options
* @return string
* @throws FileNotFoundException
* @throws OssException
*/
public function getTemporaryUrl($path, $expire = 600, $options) {
if (!$this->has($path))
throw new FileNotFoundException($path.' not found');
$method = OssClient::OSS_HTTP_GET;
if (Arr::has($options, OssClient::OSS_METHOD)) {
$method = $options['method'];
}
return $this->getClient()
->signUrl(
$this->getBucket(),
$path,
$expire,
$method,
$options
);
}


/**
* The the ACL visibility.
*
Expand Down Expand Up @@ -608,7 +639,7 @@ protected function normalizeResponse(array $object, $path = null)

return $result;
}

$result = array_merge($result, Util::map($object, static::$resultMap), ['type' => 'file']);

return $result;
Expand All @@ -629,7 +660,7 @@ protected function getOptions(array $options = [], Config $config = null)
$options = array_merge($options, $this->getOptionsFromConfig($config));
}

return array(OssClient::OSS_HEADERS => $options);
return $options;
}

/**
Expand Down
17 changes: 13 additions & 4 deletions src/AliOssServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Jacobcyl\AliOSS\Plugins\PutFile;
use Jacobcyl\AliOSS\Plugins\PutRemoteFile;
use Jacobcyl\AliOSS\Plugins\SignUrl;
use Jacobcyl\AliOSS\Plugins\GetProcessUrl;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;
Expand Down Expand Up @@ -36,23 +38,30 @@ public function boot()

$cdnDomain = empty($config['cdnDomain']) ? '' : $config['cdnDomain'];
$bucket = $config['bucket'];
$ssl = empty($config['ssl']) ? false : $config['ssl'];
$ssl = empty($config['ssl']) ? false : $config['ssl'];
$isCname = empty($config['isCName']) ? false : $config['isCName'];
$securityToken = empty($config['securityToken']) ? null : $config['securityToken'];
$debug = empty($config['debug']) ? false : $config['debug'];

$endPoint = $config['endpoint']; // 默认作为外部节点
$epInternal= $isCname?$cdnDomain:(empty($config['endpoint_internal']) ? $endPoint : $config['endpoint_internal']); // 内部节点
// $epInternal= $isCname?$cdnDomain:(empty($config['endpoint_internal']) ? $endPoint : $config['endpoint_internal']); // 内部节点
$epInternal= (empty($config['endpoint_internal']) ? $endPoint : $config['endpoint_internal']); // 内部节点

if($debug) Log::debug('OSS config:', $config);

$client = new OssClient($accessId, $accessKey, $epInternal, $isCname);
$client = new OssClient($accessId, $accessKey, $epInternal, $isCname, $securityToken);
$adapter = new AliOssAdapter($client, $bucket, $endPoint, $ssl, $isCname, $debug, $cdnDomain);

//Log::debug($client);
$filesystem = new Filesystem($adapter);

$filesystem->addPlugin(new PutFile());
$filesystem->addPlugin(new PutRemoteFile());
//增加使用签名URL进行临时授权
$filesystem->addPlugin(new SignUrl());

//增加图片处理的方法
$filesystem->addPlugin(new GetProcessUrl());
//$filesystem->addPlugin(new CallBack());
return $filesystem;
});
Expand Down
50 changes: 50 additions & 0 deletions src/Plugins/GetProcessUrl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* Created by summer.
* User: summer
* Date: 18/7/22
* Time: 下午7:03
*/

namespace Jacobcyl\AliOSS\Plugins;

use League\Flysystem\Plugin\AbstractPlugin;
use Illuminate\Contracts\Filesystem\FileNotFoundException;

class GetProcessUrl extends AbstractPlugin
{

/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'getProcessUrl';
}

/**
* 对oss图片进行操作
* 阿里云 oss 帮助文档:https://help.aliyun.com/document_detail/44688.html?spm=a2c4g.11186623.6.1199.40572e934MoHWu
* @param $path 文件路径
* @param string $action 操作名称
* @param array $option 操作参数
* @return string 返回 url 链接地址
* @throws \Exception
*/
public function handle($path, $action = 'resize', $option = ['m' => 'fixed','h' => '100','w' => '100']){
if(empty($action) || empty($option)){
throw new \Exception('操作名称和操作参数不能为空!');
}

$url = $this->filesystem->getAdapter()->getUrl($path);

$param = '';
foreach ($option as $key => $value){
$param .= ','.$key.'_'.$value;
}

return $url.'?x-oss-process=image/'.$action.$param;
}
}
5 changes: 2 additions & 3 deletions src/Plugins/PutFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

namespace Jacobcyl\AliOSS\Plugins;

use Illuminate\Support\Facades\Log;
use League\Flysystem\Config;
use League\Flysystem\Plugin\AbstractPlugin;

Expand All @@ -30,7 +29,7 @@ public function handle($path, $filePath, array $options = []){
if (method_exists($this->filesystem, 'getConfig')) {
$config->setFallback($this->filesystem->getConfig());
}

return (bool)$this->filesystem->getAdapter()->writeFile($path, $filePath, $config);
}
}
}
31 changes: 31 additions & 0 deletions src/Plugins/SignUrl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* Created by summer.
* User: summer
* Date: 18/7/22
* Time: 下午7:03
*/

namespace Jacobcyl\AliOSS\Plugins;

use League\Flysystem\Plugin\AbstractPlugin;
use Illuminate\Contracts\Filesystem\FileNotFoundException;

class SignUrl extends AbstractPlugin
{

/**
* Get the method name.
*
* @return string
*/
public function getMethod()
{
return 'signUrl';
}

public function handle($path, $timeout = 600){
if (!$this->filesystem->getAdapter()->has($path)) throw new FileNotFoundException($path.' not found');
return $this->filesystem->getAdapter()->getClient()->signUrl($this->filesystem->getAdapter()->getBucket(),$path,$timeout);
}
}