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