使用PHP操作MinIO

最近实验了下MinIO,发现这个分布式存储还是很好用的,具体不做赘述。此处记录下使用PHP操作存储桶下的文件及文件夹。

我使用了yii2框架(其实并没有使用到yii中从函数),操作minio的前提是要先下载一个模块:aws-sdk-php,minio自己的sdk并不支持PHP(minio api 文档),但是它支持亚马逊s3的对象存储,使用亚马逊s3的标准也能操作minio。

首先,在yii2项目根目录下,使用composer安装下s3工具包。

composer require aws/aws-sdk-php

若不想使用composer,或者没有条件使用可以下载zip包(下载链接),可以参考亚马逊s3文档,文档地址为:安装AWS SDK for PHP版本 3 - AWS SDK for PHP

工具包安装完毕,就可以调用工具包了,我写了一个简单的对桶中文件及文件夹的代码示例,如下:

s3Client = new S3Client([
            'version' => 'latest',
            'region'  => 'cn-north-1', //China (Beijing)
            'endpoint' => $this->endpoint,
            'use_path_style_endpoint' => true,
            'credentials' => [
                'key'    => $this->key,
                'secret' => $this->secret,
            ],
        ]);
    }

    /**
     * 判断 bucket是否存在
     * @param $bucket
     * @return bool
     * @author zsh
     */
    public function bucketExist($bucket = null)
    {
        return $this->s3Client->doesBucketExist($bucket);
    }

    /**
     * 判断bucket是否存在的另一种写法
     * @param $bucket
     * @return bool
     */
    public function bucketExists($bucket = null)
    {
        $result = $this->s3Client->listBuckets();
        $names = $result->search('Buckets[].Name');

        if($bucket){
            if(!in_array($bucket, $names)){
                return false;
            }
        }else{
            if(!in_array($this->bucket, $names)){
                return false;
            }
        }

        return true;
    }

    /**
     * 判断 查询对象是否存在
     * @param $bucket
     * @return bool
     */
    public function objectExist($object)
    {
        return $this->s3Client->doesObjectExist($this->bucket, $object);

    }

    /**
     * 上传
     * @param $objectPath
     * @param $objectName
     * @return bool|array
     */
    public function upLoadObject($objectPath, $objectName = null)
    {
        if(!$objectName){
            $objectName = basename($objectPath);
        }

        $uploader = new MultipartUploader($this->s3Client, $objectPath, [
            'bucket' => $this->bucket,
            'key' => $objectName,
        ]);

        $result=$uploader->upload();

        if(isset($result["@metadata"]["statusCode"]) && $result["@metadata"]["statusCode"] == 200){
            return [
                'bucket' => $this->bucket,
                'name' => $objectName,
                'path' => $this->bucket . '/' . $objectName
            ];
        }else{
            return false;
        }
    }

    /**
     * 上传文件到某文件夹下(上传函数upLoadObject也能实现此功能,可自己研究下)
     * @param $objectPath : 本地文件路径 li:/tmp/test.txt
     * @param $folderPath : minio中桶下的文件夹路径 li:folder/test
     * @param $objectName : 对象名称(重命名用) li: abc.txt
     * @return bool|array
     */
    public function upLoadObjectToFolder($objectPath, $folderPath, $objectName = null)
    {
        if(!$objectName){
            $objectName = basename($objectPath);
        }

        $key = $folderPath . '/' . $objectName;

        $result = $this->s3Client->putObject([
            'Bucket' => $this->bucket,
            'Key' => $key,
            'Body' => file_get_contents($objectPath) //要上传的文件
        ]);

        if(isset($result["@metadata"]["statusCode"]) && $result["@metadata"]["statusCode"] == 200){
            return [
                'bucket' => $this->bucket,
                'name' => $objectName,
                'path' => $this->bucket . '/' . $key
            ];
        }else{
            return false;
        }
    }

    /**
     * 多文件上传
     * @param $objectPathArr
     * @return array
     */
    public function batchUpload($objectPathArr)
    {
        //路径数组
        $pathArr = array();
        $s3 = $this->s3Client;

        foreach ($objectPathArr as $object) {

            if(file_exists($object)){
                //文件扩展名
                $extend = substr(strrchr($object,'.'),1);

                //文件名
                $fileName = date('Ymd') . '-' . uniqid() . '.' . $extend;

                $return = $s3->putObject([
                    'Bucket' => $this->bucket, //存储桶名称
                    'Key' => $fileName, //文件名(包括后缀名)
                    'Body' => file_get_contents($object) //要上传的文件
                ]);

                if (isset($return['@metadata']['statusCode']) && $return['@metadata']['statusCode'] == 200) {

                    $pathArr[] = [
                        'bucket' => $this->bucket,
                        'name' => $fileName,
                        'path' => $this->bucket . '/' . $fileName
                    ];

                } else {
                    //此处可增加日志记录
                    continue;
                }
            }
        }

        return $pathArr;
    }

    /**
     * 复制(重命名文件)
     * @param $sourceObject
     * @param $objectName
     * @return bool|array
     */
    public function copyObject($sourceObject, $objectName = null)
    {
        if(!$objectName){
            $extend = substr(strrchr($sourceObject,'.'),1);
            $objectName = date('Ymd') . '-' . uniqid() . '.' .$extend;
        }

        //源对象需包含桶+key
        $source = '/' . $this->bucket . '/' . $sourceObject;

        $result = $this->s3Client->copyObject([
            'Bucket' => $this->bucket, //存储桶名称
            'CopySource' => $source,
            'Key' => $objectName,
        ]);

        if(isset($result["@metadata"]["statusCode"]) && $result["@metadata"]["statusCode"] == 200){
            return [
                'bucket' => $this->bucket,
                'name' => $objectName,
                'path' => $this->bucket . '/' . $objectName
            ];
        }else{
            return false;
        }
    }

    /**
     * 获取单个对象信息
     * @param $object
     * @return array|mixed|null
     */
    public function getMetaData($object){
        $retrive = $this->s3Client->getObject([
            'Bucket' => $this->bucket,
            'Key'    => $object,
        ]);

        if(!isset($retrive['@metadata'])){
            return [];
        }

        return $retrive['@metadata'];
    }

    /**
     * 获取对象连接
     * @param $object : 对象路径 例:若在文件夹内 aaa/bbb/ccc.png 桶根目录下 ddd.png
     * @param $expires : 有效期
     * @return string
     */
    public function getUrl($object, $expires = null){
        $cmd = $this->s3Client->getCommand('GetObject', [
            'Bucket' => $this->bucket,
            'Key' => $object
        ]);

        if(!$expires){
            $expires = '+1 days';
        }

        $request=$this->s3Client->createPresignedRequest($cmd,$expires);
        $presignedUrl = (string)$request->getUri();

        return $presignedUrl;

        //测试-图片
        //return "";
    }

    /**
     * 获取多个对象信息
     * @param $data
     * @return array|mixed
     */
    public function getAll($data){
        $param = [
            'Bucket' => $this->bucket
        ];

        if(isset($data['num'])){
            $param['MaxKeys'] = $data['num'];
        }

        if(isset($data['prefix'])){
            $param['Prefix'] = $data['prefix'];
        }

        $retrive = $this->s3Client->listObjects($param);

        if(isset($retrive['Contents'])){
            return $retrive['Contents'];
        }else{
            return [];
        }
    }

    /**
     * 删除单个文件
     * @param $object
     * @return bool
     */
    public function deleteObject($object){

        $result = $this->s3Client->deleteObject([
            'Bucket' => $this->bucket,
            'Key' => $object,
        ]);

        if(isset($result['@metadata']['statusCode']) && $result['@metadata']['statusCode'] == 204){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 删除多个文件
     * @param $objectArr
     * @return bool
     */
    public function batchDeleteObject($objectArr)
    {
        $keys = array();

        foreach ($objectArr as $item) {
            $keys[] = array('Key' => $item);
        }

        $s3 = $this->s3Client;

        $result = $s3->deleteObjects([
            'Bucket' => $this->bucket,
            'Delete' => ['Objects' => $keys]
        ]);

        if(isset($result["@metadata"]["statusCode"]) && $result["@metadata"]["statusCode"] == 200){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 上传文件夹
     * @param $folderPath : 文件夹路径
     * @param $folderName : 指定文件夹名称
     * @return bool
     */
    public function uploadFolder($folderPath, $folderName = null)
    {
        if(!$folderName) {
            $folderName = basename($folderPath);
        }

        $keyPrefix = $folderName . '/';

        $options['params']['ACL'] = 'public-read';

        $this->s3Client->uploadDirectory($folderPath, $this->bucket, $keyPrefix , $options);

        return true;
    }

    /**
     * 删除文件夹
     * @param $folderPath
     * @return bool
     */
    public function deleteFolder($folderPath)
    {
        $folderName = basename($folderPath);

        $keyPrefix = $folderName . '/';

        $this->s3Client->deleteMatchingObjects($this->bucket, $keyPrefix);

        return true;
    }

}

在本地使用docker安装一个minio的命令:

先docker pull minio的镜像。由于我本地是windows,所以目录映射就写为这样D:\data\minio\data:/data,本地9000端口已经被php占用,所以分配9001给minio使用。


docker run --name minio -p 9001:9000 -p 9090:9090 -d --restart=always -e "MINIO_ROOT_USER=admin" -e "MINIO_ROOT_PASSWORD=admin123" -v D:\data\minio\data:/data -v D:\data\minio\config:/root/.minio minio/minio:[版本tag] server /data --console-address ':9090'

启动后,访问http://127.0.0.1:9090/browser即可进入控制台

你可能感兴趣的:(php,MinIO,php,开发语言,MinIO)