美文网首页
阿里云WEB直传php服务端

阿里云WEB直传php服务端

作者: 安晓生 | 来源:发表于2021-01-08 15:04 被阅读0次

阿里云服务端签名验证:
YII2框架的

/**
 * Class AliOss
 * @package common\components
 */
class AliyunOss extends Component
{
    public $accessKeyId;

    public $accessKeySecret;

    public $endpoint;

    public $bucket;

    public $objectBasePath;

    /**
     * @var OssClient client
     */
    public $client = null;

    /**
     * init
     * @throws \Exception
     * 2019/3/26 17:07
     */
    public function init()
    {
        $this->validateConfig();
        $this->objectBasePath = YII_ENV.'/'.trim($this->objectBasePath, '/');
        if ($this->client === null) {
            $this->client = new OssClient($this->accessKeyId, $this->accessKeySecret, $this->endpoint);
        }
    }

    /**
     * validateConfig
     * @throws Exception
     * 2019/3/26 17:07
     */
    protected function validateConfig()
    {
        if (!$this->objectBasePath) {
            throw new Exception("请设置objectBasePath");
        }
        if (!$this->accessKeyId) {
            throw new Exception("请设置accessKeyId");
        }
        if (!$this->accessKeySecret) {
            throw new Exception("请设置accessKeySecret");
        }
        if (!$this->endpoint) {
            throw new Exception("请设置endpoint");
        }
        if (!$this->bucket) {
            throw new Exception("请设置bucket");
        }
    }


    /**
     * close
     * 2019/3/26 18:06
     */
    public function close()
    {
        if ($this->client !== null) {
            Yii::trace('Closing OssClient', __METHOD__);

            $this->client = null;
        }
    }

    /**
     * uploadFile
     * @param string $object oss object名称
     * @param string $localFile 本地文件
     *
     * @return |null
     * @throws Exception
     * 2019/3/26 17:15
     */
    public function uploadFile($object, $localFile)
    {
        $object = $this->formatObject($object);
        try {
            if ($this->client->uploadFile($this->bucket, $object, $localFile)) {
                return $object;
            }
            return false;
        } catch (OssException $e) {
            throw new Exception($e->getMessage(), $e->getCode(), $e);
        }
    }

    /**
     * uploadFiles
     * @param $files
     *
     * @return array
     * @throws \Exception
     * 2019/3/26 17:20
     */
    public function uploadFiles($files)
    {
        $res = [];
        foreach ($files as $object => $localFile) {
            $res[$object] = $this->uploadFile($object, $localFile);
        }
        return $res;
    }

    /**
     * 下载oss object到本地
     * downloadObject
     * @param string $object oss object
     * @param string $savePath 保存到本地的路径
     *
     * @return string
     * 2019/3/27 14:14
     */
    public function downloadObject($object, $savePath)
    {
        $options = array(
            OssClient::OSS_FILE_DOWNLOAD => $savePath,
        );
        $object = $this->formatObject($object);
        return $this->client->getObject($this->bucket, $object, $options);
    }

    /**
     * 删除oss图片
     * deleteFile
     * @param $object
     *
     * @return array|bool
     * 2019/3/27 14:32
     */
    public function deleteFile($object)
    {
        if (is_array($object)) {
            $res = [];
            foreach ($object as $obj) {
                if (!$this->deleteFile($obj)) {
                    $res['fail']++;
                }
                $res['success']++;
            }
            return $res;
        }
        $object = $this->formatObject($object);
        if ($this->client->deleteObject($this->bucket, $object)) {
            return true;
        }
        return false;
    }

    /**
     * 通过multipart上传文件
     * multiuploadFile
     * @param $object
     * @param $localFile
     *
     * @return |null
     * @throws Exception
     * 2019/3/26 17:25
     */
    public function multiuploadFile($object, $localFile)
    {
        $object = $this->formatObject($object);
        $options = array();
        try {
            return $this->client->multiuploadFile($this->bucket, $object, $localFile, $options);
        } catch (OssException $e) {
            throw new Exception($e->getMessage(), $e->getCode(), $e);
        }
    }


    /**
     * 获取视频封面图
     * @param $video string 视频路径
     * @param $second int 截取时间输入其它默认为0
     * @param $width int 宽度px $height int 高度px
     * @return string 图片相对路径
     */
    public function getVideoImg($video, $second = 5, $width = 720, $height = 400)
    {
        $second = $second ? $second : 5;
        $width = $width ? $width : 720;
        $height = $height ? $height : 400;
        $imgUrl = "?x-oss-process=video/snapshot,t_". $second*1000 . ",f_png,w_".$width.",h_".$height;
        return $video.$imgUrl;
    }

    /**
     * formatObject
     * @param $object
     *
     * @return string
     * 2019/3/26 17:57
     */
    public function formatObject($object)
    {
        $object = trim($object, '/');
        $res = yii\helpers\StringHelper::startsWith($object, $this->objectBasePath);
        if (!$res) {
            $object = $this->objectBasePath.'/'.$object;
        }
        return trim($object, '/');
    }


    /**
     * PostObject签名policy
     *
     * @param array $policy_condition policy规则
     * @param array $callback_params 回调配置
     * @param int   $expire policy超时时间,即这个policy过了这个有效时间,将不能访问。默认30s
     * @link https://help.aliyun.com/document_detail/31927.html?spm=a2c4g.11186623.6.1567.b8e97d2dMSThOz 签名并回调上传文档
     * @link https://help.aliyun.com/document_detail/91771.html?spm=a2c4g.11186623.2.15.21967eae5edmiX#concept-nhs-ldt-2fb 签名并回调上传文档
     * @link http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/92590/APP_zh/1539603337889/aliyun-oss-appserver-php-master.zip?spm=a2c4g.11186623.2.14.6b5e4c07xtvc9D&file=aliyun-oss-appserver-php-master.zip php签名官方demo
     * @link https://help.aliyun.com/document_detail/31988.html?spm=a2c4g.11186623.2.22.21967eaeMXpMOk#section-d5z-1ww-wdb policy写法
     * @link https://help.aliyun.com/document_detail/31989.html?spm=a2c4g.11186623.2.22.58dd4c07J5iEMJ#section-btz-phx-wdb callback写法
     * @return array
     */
    public function signPolicy(array $policy_condition = [],array $callback_params = [],int $expire = 30)
    {
        //用户上传文件时指定的前缀。
        $objectDir = $this->formatObject($this->objectBasePath)."/";

        if(!$policy_condition) {
            //最大文件大小.用户可以自己设置,单位字节
            $length_condition = ['content-length-range', 0, 1048576000];
            // 表示用户上传的数据,必须是以$dir开始,不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录。
            $start_condition = ['starts-with', '$key', $objectDir];
            $policy_condition = [$length_condition,$start_condition];
        }

        //设置该policy超时时间. 即这个policy过了这个有效时间,将不能访问。
        $end = time() + $expire;

        $policy_array = [
            'expiration'=>DateTimeHelper::gmt($end),
            'conditions'=>$policy_condition
        ];
        $base64_policy = base64_encode(json_encode($policy_array));
        $signature = base64_encode(hash_hmac('sha1', $base64_policy, $this->accessKeySecret, true));

        $result = [];
        $result['accessid'] = $this->accessKeyId;
        $result['host'] = $this->getBucketHost();
        $result['policy'] = $base64_policy;
        $result['signature'] = $signature;
        $result['expire'] = $end;
        $result['dir'] = $objectDir;
        if($callback_params){
            $result['callback'] = base64_encode(json_encode($callback_params));
        }
        return $result;
    }

    /**
     * 获取带bucket的host
     * @return string
     */
    private function getBucketHost()
    {
        $ret_endpoint = null;
        $endpoint = $this->endpoint;
        if (strpos($endpoint, 'http://') === 0) {
            $http = "http://";
            $ret_endpoint = substr($endpoint, strlen('http://'));
        } elseif (strpos($endpoint, 'https://') === 0) {
            $http = "https://";
            $ret_endpoint = substr($endpoint, strlen('https://'));
        } else {
            $ret_endpoint = $endpoint;
            $http = "https";
        }
        return $http.$this->bucket.'.'.$ret_endpoint;
    }

    /**
     * 复制fromObject到新的toObject
     * @param string|array $fromObject 源object
     * @param string|array $toObject 目标object
     * @param string|null $fromBucket 源bucket
     * @param string|null $toBucket 目标bucket
     * @param null $options
     *
     * @return array|bool
     * @throws OssException
     */
    public function copyFile($fromObject,$toObject,$fromBucket = NULL,$toBucket = NULL,$options = NULL)
    {
        if (is_array($fromObject)) {
            $res = [];
            foreach ($fromObject as $k=>$obj) {
                if (!$this->copyFile($obj,$toObject[$k],$fromBucket,$toBucket,$options)) {
                    $res['fail']++;
                }
                $res['success']++;
            }
            return $res;
        }
        $fromBucket = $fromBucket ?? $this->bucket;
        $toBucket = $toBucket ?? $this->bucket;
        if ($this->client->copyObject($fromBucket,$fromObject,$toBucket,$toObject,$options)) {
            return true;
        }
        return false;
    }

    /**
     * 移动fromObject到新的toObject,并删除fromObject
     * @param string|array $fromObject 源object
     * @param string|array $toObject 目标object
     * @param string|null $fromBucket 源bucket
     * @param string|null $toBucket 目标bucket
     * @param null $options
     *
     * @return array|bool
     * @throws OssException
     */
    public function moveFile($fromObject,$toObject,$fromBucket = NULL,$toBucket = NULL,$options = NULL)
    {
        if (is_array($fromObject)) {
            $res = [];
            foreach ($fromObject as $k=>$obj) {
                if (!$this->copyFile($obj,$toObject[$k],$fromBucket,$toBucket,$options)) {
                    $res['fail']++;
                }
                $res['success']++;
            }
            return $res;
        }
        $fromBucket = $fromBucket ?? $this->bucket;
        $toBucket = $toBucket ?? $this->bucket;
        if ($this->client->copyObject($fromBucket,$fromObject,$toBucket,$toObject,$options)) {
            if ($this->client->deleteObject($fromBucket, $fromObject)) {
                return true;
            }
            return true;
        }
        return false;
    }

laravel框架的

<?php

namespace App\Utils;

use Illuminate\Support\Facades\Log;
use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Model\RefererConfig;

class OssUtil
{
    private static $_instance;
    protected $ossClient;
    protected $bucket;
    protected $endpoint;
    protected $ossConfig;

    public function __construct($bucket = null){
        $this->ossConfig = config('oss');
        $this->ossClient = new OssClient($this->ossConfig['accessKeyId'],$this->ossConfig['accessKeySecret'],$this->ossConfig['endpoint']);
        if($bucket){
            $this->bucket = $bucket;
        }else{
            $this->bucket = $this->ossConfig['default_bucket'];
        }
        $this->endpoint = $this->ossConfig['endpoint'];

        if(!empty($ossConfig['bucket_white_list'])){
            $this->setBucketReferer($this->ossConfig['default_bucket'], $this->ossConfig['bucket_white_list']);
        }

        $this->ossClient->setTimeout(3600);
        $this->ossClient->setUseSSL(false);
    }

    public static function getInstance($options = null)
    {
        if (is_null(self::$_instance)) {
            self::$_instance = new static($options);
        }
        return self::$_instance;
    }
    //生成oss对象
    public function getOssClient(){
        return $this->ossClient;
    }

    //获取bucket
    public function getBucket(){
        return $this->bucket;
    }

    //获取bucket地域
    public function getEndpoint(){
        return $this->endpoint;
    }

    //获得当次请求使用的协议头
    public function getScheme(){
        return $this->ossClient->isUseSSL() ? 'https://' : 'http://';
    }

    //获取签名
    public function getSign($dir, $size)
    {
        $dir = config('oss.object') . $dir;
        //$host的格式为https://bucketname.endpointx
        $host = $this->getScheme() . $this->bucket . '.' . $this->endpoint;
        //回调地址
        $callbackUrl = str_replace('_', '', url('/api/ossCallback', [], true));

        $callbackparam = array('callbackUrl'=>$callbackUrl,
            'callbackBody'=>'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}&format=${imageInfo.format}',
            'callbackBodyType'=>"application/x-www-form-urlencoded");
        $callbackString = json_encode($callbackparam);

        $base64CallbackBody = base64_encode($callbackString);
        $now = time();
        $expire = 60;  //设置该policy超时时间. 即这个policy过了这个有效时间,将不能访问。
        $end = $now + $expire;
        $expiration = $this->gmtIso8601($end);

        //最大文件大小.用户可以自己设置
        $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 = json_encode($arr);
        $base64Policy = base64_encode($policy);
        $stringToSign = $base64Policy;
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $this->ossConfig['accessKeySecret'], true));

        $response = array();
        $response['accessid'] = $this->ossConfig['accessKeyId'];
        $response['host'] = $host;
        $response['policy'] = $base64Policy;
        $response['signature'] = $signature;
        $response['expire'] = $end;
        $response['callback'] = $base64CallbackBody;
        $response['dir'] = $dir;  // 这个参数是设置用户上传文件时指定的前缀。
        return $response;
    }

    /**
     * 文件上传
     * @param $object string 上传的object
     * @param $filePath string 本地路径
     * @return array
     */
    public function uploadFile($object,$filePath){
        try{
            $this->ossClient->uploadFile($this->bucket,$object,$filePath);
            return ['status'=>200,'url'=>$object];
        }catch(OssException $e){
            Log::channel('daily')->info('上传oss失败',['file'=>$filePath]);
            return ['status'=>0];
        }
    }

    /**
     * 文件保存
     * @param $object string 文件的object
     * @param $filePath string 本地路径
     * @return array
     */
    public function downLoadFile($object,$filePath){
        try{

            $options = [OssClient::OSS_FILE_DOWNLOAD => $filePath];
            $result = $this->ossClient->getObject($this->bucket,$object,$options);
            return ['status'=>200,$result];
        }catch(OssException $e){
            Log::channel('daily')->info('下载失败',[$e->getMessage()]);
            return ['status'=>0];
        }
    }

    //设置白名单
    private function setBucketReferer($bucket, $whiteList)
    {
        $refererConfig = new RefererConfig();
        $refererConfig->setAllowEmptyReferer(true);

        $whiteList = explode(',', $whiteList);
        foreach ($whiteList as $key => $value) {
            $refererConfig->addReferer($value);
        }
        try {
            $this->ossClient->putBucketReferer($bucket, $refererConfig);
            return true;
        } catch (OssException $e) {
            return false;
        }
    }

    private function gmtIso8601($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";
    }
}

相关文章

网友评论

      本文标题:阿里云WEB直传php服务端

      本文链接:https://www.haomeiwen.com/subject/bexfaktx.html