Laravel-Admin Storage使用 ucloud

作用:laravel-admin 自带的images 和  multipleImage控件可直接上传到ucloud

Storage 也可直接使用 示例:

\Storage::disk('ucloud')->put('images/file.jpg', file_get_contents("public/images/loading.gif"));
//遇到一个坑 影响不大 mark一下
如果先拿这个文件名去浏览器访问了一下(提示文件不存在) 再去上传那么会上传不上去,很奇怪!!

  

三个新文件  (先放 App\Providers\UcloudLaravelAdmin 目录下吧)

1、UcloudUfileAdapter.php

<?php
namespace App\Providers\UcloudLaravelAdmin;

use League\Flysystem\Adapter\AbstractAdapter;
use League\Flysystem\Adapter\Polyfill\NotSupportingVisibilityTrait;
use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
use League\Flysystem\Adapter\Polyfill\StreamedTrait;
use League\Flysystem\Config;
use LogicException;

class UcloudUfileAdapter extends AbstractAdapter {

	use NotSupportingVisibilityTrait, StreamedTrait, StreamedCopyTrait;
	protected $ufileSdk;

	public function __construct(
	    $bucket,
        $public_key,
        $secret_key,
        $suffix = '.ufile.ucloud.cn',
        $pathPrefix = '',
        $https = false
    ) {
		$this->ufileSdk = new UfileSdk($bucket, $public_key, $secret_key, $suffix, $https);

		$this->setPathPrefix($pathPrefix);
	}

	public function read($path) {
		$path = $this->applyPathPrefix($path);
		$data = [];
		$data['contents'] = $this->ufileSdk->get($path);
		return $data;
	}

	/**
	 * Write a new file.
	 *
	 * @param string $path
	 * @param string $contents
	 * @param Config $config   Config object
	 *
	 * @return array|false false on failure file meta data on success
	 */
	public function write($path, $contents, Config $config) {
		$path = $this->applyPathPrefix($path);
		$params = $config->get('params', null);
		$mime = $config->get('mime', 'application/octet-stream');
		$checkCrc = $config->get('checkCrc', false);
		list($ret, $code) = $this->ufileSdk->put($path, $contents, ['Content-Type' => $mime]);
		return $ret;
	}

	/**
	 * Write a new file using a stream.
	 *
	 * @param string   $path
	 * @param resource $resource
	 * @param Config   $config   Config object
	 *
	 * @return array|false false on failure file meta data on success
	 */
	public function writeStream($path, $resource, Config $config) {
		$path = $this->applyPathPrefix($path);
		$params = $config->get('params', null);
		$mime = $config->get('mime', 'application/octet-stream');
		$checkCrc = $config->get('checkCrc', false);
		list($ret, $code) = $this->ufileSdk->put($path, $resource, ['Content-Type' => $mime]);
		return $ret;
	}

	/**
	 * Update a file.
	 *
	 * @param string $path
	 * @param string $contents
	 * @param Config $config   Config object
	 *
	 * @return array|false false on failure file meta data on success
	 */
	public function update($path, $contents, Config $config) {
		return $this->write($path, $contents, $config);
	}

	/**
	 * Update a file using a stream.
	 *
	 * @param string   $path
	 * @param resource $resource
	 * @param Config   $config   Config object
	 *
	 * @return array|false false on failure file meta data on success
	 */
	public function updateStream($path, $resource, Config $config) {
		return $this->writeStream($path, $resource, $config);
	}

	/**
	 * Rename a file.
	 *
	 * @param string $path
	 * @param string $newpath
	 *
	 * @return bool
	 */
	public function rename($path, $newpath) {
		throw new \Exception('not supprot');
	}

	/**
	 * Delete a file.
	 *
	 * @param string $path
	 *
	 * @return bool
	 */
	public function delete($path) {
		$path = $this->applyPathPrefix($path);
		return $this->ufileSdk->delete($path);
	}

	/**
	 * Delete a directory.
	 *
	 * @param string $dirname
	 *
	 * @return bool
	 */
	public function deleteDir($dirname) {
		throw new LogicException(get_class($this) . ' does not support ' . __FUNCTION__);
	}

	/**
	 * Create a directory.
	 *
	 * @param string $dirname directory name
	 * @param Config $config
	 *
	 * @return array|false
	 */
	public function createDir($dirname, Config $config) {
		return ['path' => $dirname];
	}

	/**
	 * Check whether a file exists.
	 *
	 * @param string $path
	 *
	 * @return array|bool|null
	 */
	public function has($path) {
		$path = $this->applyPathPrefix($path);
		return $this->ufileSdk->exists($path);
	}

	/**
	 * List contents of a directory.
	 *
	 * @param string $directory
	 * @param bool   $recursive
	 *
	 * @return array
	 */
	public function listContents($directory = '', $recursive = false) {
		throw new LogicException(get_class($this) . ' does not support ' . __FUNCTION__);
	}

	/**
	 * Get all the meta data of a file or directory.
	 *
	 * @param string $path
	 *
	 * @return array|false
	 */
	public function getMetadata($path) {
		$path = $this->applyPathPrefix($path);
		return $this->ufileSdk->meta($path);
	}

	/**
	 * Get all the meta data of a file or directory.
	 *
	 * @param string $path
	 *
	 * @return array|false
	 */
	public function getSize($path) {
		$path = $this->applyPathPrefix($path);
		$size = $this->ufileSdk->size($path);
		return array('size' => $size);
	}

	/**
	 * Get the mimetype of a file.
	 *
	 * @param string $path
	 *
	 * @return array|false
	 */
	public function getMimetype($path) {
		$path = $this->applyPathPrefix($path);
		$mimeType = $this->ufileSdk->mime($path);
		return array('mimetype' => $mimeType);
	}

	/**
	 * Get the timestamp of a file.
	 *
	 * @param string $path
	 *
	 * @return array|false
	 */
	public function getTimestamp($path) {
		$meta = $this->getMetadata($path);
		$timestamp = strtotime($meta['Last-Modified']);
		return array('timestamp' => $timestamp);
	}
	public function getUrl($path){
	    if(strpos($path, 'http')!==false){
            return $path;
        }
	    return config("filesystems.disks.ucloud.url").$path;
    }

}

2、UfileSdk.php

<?php

namespace App\Providers\UcloudLaravelAdmin;

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;

class UfileSdkException extends \Exception
{
}

class UfileSdk
{
    protected $httpClient;
    protected $bucket;
    protected $pub_key;
    protected $sec_key;
    protected $host;

    protected static function auth($bucket, $pub_key, $sec_key)
    {
        return function (callable $handler) use ($bucket, $pub_key, $sec_key) {
            return function (
                $request,
                array $options
            ) use ($handler, $bucket, $pub_key, $sec_key) {
                $path                  = $request->getUri()->getPath();
                $method                = strtoupper($request->getMethod());
                $paramToSign['method'] = $method;
                foreach (['Content-MD5', 'Content-Type', 'Date'] as $headNeedSign) {
                    $v                          = $request->getHeader($headNeedSign);
                    $paramToSign[$headNeedSign] = empty($v) ? "" : $v[0];
                }
                $authString = implode("\n", $paramToSign) . "\n";
                //合并UCloud特殊头
                $headers = $request->getHeaders();
                //标准化CanonicalizedUCloudHeaders
                foreach ($headers as $k => $v) {
                    $k = strtolower($k);
                    if (strncasecmp($k, "x-ucloud-", strlen('x-ucloud-')) !== 0) {
                        continue;
                    }
                    if (is_array($v)) {
                        $v = implode(',', $v);
                    }
                    $authString .= $k . ":" . trim($v, " ") . "\n";
                }
                //合并资源路径
                $authString .= "/" . $bucket . $path;
                $signature  = base64_encode(hash_hmac('sha1', $authString, $sec_key, true));
                $authToken  = "UCloud " . $pub_key . ":" . $signature;
                $request    = $request->withHeader('Authorization', $authToken);
                if (in_array($method, ['POST', 'PUT'])) {
                    $request = $request->withHeader('Content-Length', $request->getBody()->getSize());
                }
                return $handler($request, $options);
            };
        };
    }

    public function __construct($bucket, $pub_key, $sec_key, $suffix = '.ufile.ucloud.cn', $https = false, $debug = false)
    {
        $this->bucket  = $bucket;
        $this->pub_key = $pub_key;
        $this->sec_key = $sec_key;
        $this->host    = ($https ? 'https://' : 'http://') . $bucket . $suffix;
        $stack         = new HandlerStack();
        $stack->setHandler(new CurlHandler());
        $stack->push(static::auth($bucket, $pub_key, $sec_key));
        $this->httpClient = new Client(['base_uri' => $this->host, 'handler' => $stack, 'debug' => $debug]);
    }

    public function put($key_name, $contents, $headers = [])
    {
        $headers = [];
        $resp    = $this->httpClient->request('PUT', $key_name, [
            'headers' => $headers,
            'body'    => $contents]);
        if($resp->getStatusCode() == 200){
            return [$key_name, $resp->getStatusCode()];
        }
        return [$resp->getBody()->getContents(), $resp->getStatusCode()];
    }

    public function putFile($key_name, $filePath, $headers = [])
    {
        $resp = $this->httpClient->request('PUT', $key_name, [
            'headers' => $headers,
            'body'    => fopen($filePath, 'r')]);
        if($resp->getStatusCode() == 200){
            return [$key_name, $resp->getStatusCode()];
        }
        return [$resp->getBody()->getContents(), $resp->getStatusCode()];
    }

    public function get($key_name)
    {
        $resp = $this->httpClient->get($key_name);
        if ($resp->getStatusCode() != 200) {
            throw new UfileSdkException("get $key_name error :" . $resp->getStatusCode());
        }
        return $resp->getBody()->getContents();
    }

    public function exists($key_name)
    {
        $resp = $this->httpClient->head($key_name);
        return $resp->getStatusCode() == 200;
    }

    public function size($key_name)
    {
        $resp = $this->httpClient->head($key_name);
        if ($resp->getStatusCode() != 200) {
            throw new UfileSdkException("size $key_name error :" . $resp->getStatusCode());
        }
        return (int)$resp->getHeader('Content-Length')[0];
    }

    public function mime($key_name)
    {
        $resp = $this->httpClient->head($key_name);
        if ($resp->getStatusCode() != 200) {
            throw new UfileSdkException("size $key_name error :" . $resp->getStatusCode());
        }
        return $resp->getHeader('Content-Type')[0];
    }

    public function delete($key_name)
    {
        $resp = $this->httpClient->delete($key_name);
        if (!in_array($resp->getStatusCode(), [200, 204])) {
            throw new UfileSdkException("delete $key_name error :" . $resp->getStatusCode());
        }
        return true;
    }

    public function meta($key_name)
    {
        $resp = $this->httpClient->head($key_name);
        if ($resp->getStatusCode() != 200) {
            throw new UfileSdkException("size $key_name error :" . $resp->getStatusCode());
        }
        $meta = [];
        foreach ($resp->getHeaders() as $k => $v) {
            $meta[$k] = $v[0];
        }
        return $meta;
    }

}

3、UfileServiceProvider.php

<?php
namespace App\Providers\UcloudLaravelAdmin;

use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;

class UfileServiceProvider extends ServiceProvider {

	public function boot() {
	    /*
	     * extend方法的第一个参数是驱动名称,
	     * 第二个参数是获取$app和$config变量的闭包。
	     * 该解析器闭包必须返回一个League\Flysystem\Filesystem实例。
	     * $config变量即为 配置文件config/filesystems.php中为特定磁盘定义的选项。
	     * 创建好注册扩展的服务提供者后,就可以使用配置文件config/filesystem.php中的ucloud驱动了
	     */
		\Storage::extend(
			'ucloud',
			function ($app, $config) {
				$ufileAdapter = new UcloudUfileAdapter(
					$config['bucket'],
					$config['public_key'],
					$config['secret_key'],
					$config['suffix'],
					$config['prefix']
				);
				$fs = new Filesystem($ufileAdapter);
				return $fs;
			}
		);
	}

	public function register() {

	}
}

 

修改2个文件

1、config/app.php  中providers数组里 添加

App\Providers\UcloudLaravelAdmin\UfileServiceProvider::class

2、config/filesystems.php disks数组里 添加

        'ucloud' => [
            'driver'     => 'ucloud',
            'bucket'     => '',
            'public_key' => '',
            'secret_key' => '',
            'suffix'     => '.ufile.ucloud.cn',//图片上传地址
            'prefix'     => '',
            'url'        => env('OSS_HOST'),//图片访问CDN地址
        ],

3、config/admin.php  upload 数组里 更改

'disk' => 'ucloud',

  

需要安装的组件

guzzlehttp/guzzle
league/flysystem

  

posted @ 2020-03-25 17:19  wangxusummer  阅读(774)  评论(0)    收藏  举报