├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml └── src ├── Plugins └── ImagePreviewUrl.php ├── UpyunAdapter.php └── UpyunServiceProvider.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | composer.lock 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 JellyBool 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Laravel Flysystem Upyun (又拍云)

2 | 3 |

:floppy_disk: 又拍云 Flysystem 实现,可直接用于 Laravel 项目。

4 | 5 | 6 |

7 | Build Status 8 | Quality Score 9 | Latest Stable Version 10 | Latest Unstable Version 11 | Total Downloads 12 | License 13 |

14 | 15 | 16 | # Requirement 17 | 18 | - PHP >= 5.5.9 19 | 20 | # 视频教程 21 | > 视频使用教程(当然是免费的):https://www.codecasts.com/series/awesome-laravel-packages/episodes/8 22 | 23 | # 安装 24 | 25 | 直接可以通过 composer 来安装: 26 | ```shell 27 | 28 | $ composer require "jellybool/flysystem-upyun" 29 | ``` 30 | 31 | # 使用 32 | 33 | ## 1.在一般项目中使用 34 | 35 | ```php 36 | 37 | use League\Flysystem\Filesystem; 38 | use JellyBool\Flysystem\Upyun\UpyunAdapter; 39 | 40 | $bucket = 'your-bucket-name'; 41 | $operator = 'oparator-name'; 42 | $password = 'operator-password'; 43 | $domain = 'xxxxx.b0.upaiyun.com'; // 或者 https://xxxx.b0.upaiyun.com 44 | 45 | $adapter = new UpyunAdapter($bucket, $operator, $password, $domain); 46 | 47 | $flysystem = new Filesystem($adapter); 48 | 49 | ``` 50 | 51 | ## 2.在 Laravel 中使用 52 | 53 | 1.在 `config/app.php` 添加 `UpyunServiceProvider`: 54 | 55 | ```php 56 | 57 | 'providers' => [ 58 | // Other service providers... 59 | JellyBool\Flysystem\Upyun\UpyunServiceProvider::class, 60 | ], 61 | ``` 62 | 2.在 `config/filesystems.php` 的 `disks` 中添加下面的配置: 63 | 64 | ```php 65 | 66 | return [ 67 | //... 68 | 'upyun' => [ 69 | 'driver' => 'upyun', 70 | 'bucket' => 'your-bucket-name',// 服务名字 71 | 'operator' => 'oparator-name', // 操作员的名字 72 | 'password' => 'operator-password', // 操作员的密码 73 | 'domain' => 'xxxxx.b0.upaiyun.com', // 服务分配的域名 74 | 'protocol' => 'https', // 服务使用的协议,如需使用 http,在此配置 http 75 | ], 76 | //... 77 | ]; 78 | 79 | ``` 80 | 81 | # API 和方法调用 82 | 83 | ```php 84 | 85 | bool $flysystem->write('file.md', 'contents'); 86 | 87 | bool $flysystem->writeStream('file.md', fopen('path/to/your/local/file.jpg', 'r')); 88 | 89 | bool $flysystem->update('file.md', 'new contents'); 90 | 91 | bool $flysystem->updateStram('file.md', fopen('path/to/your/local/file.jpg', 'r')); 92 | 93 | bool $flysystem->rename('foo.md', 'bar.md'); 94 | 95 | bool $flysystem->copy('foo.md', 'foo2.md'); 96 | 97 | bool $flysystem->delete('file.md'); 98 | 99 | bool $flysystem->has('file.md'); 100 | 101 | string|false $flysystem->read('file.md'); 102 | 103 | array $flysystem->listContents(); 104 | 105 | array $flysystem->getMetadata('file.md'); 106 | 107 | int $flysystem->getSize('file.md'); 108 | 109 | string $flysystem->getUrl('file.md'); 110 | 111 | string $flysystem->getMimetype('file.md'); 112 | 113 | int $flysystem->getTimestamp('file.md'); 114 | 115 | ``` 116 | 117 | # License 118 | 119 | MIT 120 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jellybool/flysystem-upyun", 3 | "description": "Flysystem and Laravel adapter for the Upyun storage.", 4 | "keywords": ["Laravel","upyun","又拍","又拍云"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "JellyBool", 9 | "email": "jellybool@outlook.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.5.9", 14 | "league/flysystem": "^1.0", 15 | "upyun/sdk": "^3.0" 16 | }, 17 | "require-dev": { 18 | "php": ">=5.6.0", 19 | "phpunit/phpunit": "~5.7" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "JellyBool\\Flysystem\\Upyun\\": "src/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "JellyBool\\Flysystem\\Upyun\\UpyunServiceProvider" 30 | ] 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Plugins/ImagePreviewUrl.php: -------------------------------------------------------------------------------- 1 | filesystem->getAdapter()->getUrl($path); 27 | } 28 | } -------------------------------------------------------------------------------- /src/UpyunAdapter.php: -------------------------------------------------------------------------------- 1 | bucket = $bucket; 48 | $this->operator = $operator; 49 | $this->password = $password; 50 | $this->domain = $domain; 51 | $this->protocol = $protocol; 52 | } 53 | 54 | /** 55 | * @param string $path 56 | * @param string $contents 57 | * @param Config $config 58 | */ 59 | public function write($path, $contents, Config $config) 60 | { 61 | return $this->client()->write($path, $contents); 62 | } 63 | 64 | /** 65 | * @param string $path 66 | * @param resource $resource 67 | * @param Config $config 68 | */ 69 | public function writeStream($path, $resource, Config $config) 70 | { 71 | return $this->client()->write($path, $resource); 72 | } 73 | 74 | /** 75 | * @param string $path 76 | * @param string $contents 77 | * @param Config $config 78 | */ 79 | public function update($path, $contents, Config $config) 80 | { 81 | return $this->write($path, $contents, $config); 82 | } 83 | 84 | /** 85 | * @param string $path 86 | * @param resource $resource 87 | * @param Config $config 88 | */ 89 | public function updateStream($path, $resource, Config $config) 90 | { 91 | return $this->writeStream($path, $resource, $config); 92 | } 93 | 94 | /** 95 | * @param string $path 96 | * @param string $newpath 97 | */ 98 | public function rename($path, $newpath) 99 | { 100 | $this->copy($path,$newpath); 101 | return $this->delete($path); 102 | } 103 | 104 | /** 105 | * @param string $path 106 | * @param string $newpath 107 | */ 108 | public function copy($path, $newpath) 109 | { 110 | $this->writeStream($newpath, fopen($this->getUrl($path), 'r'), new Config()); 111 | return true; 112 | } 113 | 114 | /** 115 | * @param string $path 116 | */ 117 | public function delete($path) 118 | { 119 | return $this->client()->delete($path); 120 | } 121 | 122 | /** 123 | * @param string $dirname 124 | */ 125 | public function deleteDir($dirname) 126 | { 127 | return $this->client()->deleteDir($dirname); 128 | } 129 | 130 | /** 131 | * @param string $dirname 132 | * @param Config $config 133 | */ 134 | public function createDir($dirname, Config $config) 135 | { 136 | return $this->client()->createDir($dirname); 137 | } 138 | 139 | /** 140 | * @param string $path 141 | * @param string $visibility 142 | */ 143 | public function setVisibility($path, $visibility) 144 | { 145 | return true; 146 | } 147 | 148 | /** 149 | * @param string $path 150 | */ 151 | public function has($path) 152 | { 153 | return $this->client()->has($path); 154 | } 155 | 156 | /** 157 | * @param string $path 158 | */ 159 | public function read($path) 160 | { 161 | $contents = file_get_contents($this->getUrl($path)); 162 | return compact('contents', 'path'); 163 | } 164 | 165 | /** 166 | * @param string $path 167 | */ 168 | public function readStream($path) 169 | { 170 | $stream = fopen($this->getUrl($path), 'r'); 171 | return compact('stream', 'path'); 172 | } 173 | 174 | /** 175 | * @param string $directory 176 | * @param bool $recursive 177 | */ 178 | public function listContents($directory = '', $recursive = false) 179 | { 180 | $list = []; 181 | 182 | $result = $this->client()->read($directory, null, [ 'X-List-Limit' => 100, 'X-List-Iter' => null]); 183 | 184 | foreach ($result['files'] as $files) { 185 | $list[] = $this->normalizeFileInfo($files, $directory); 186 | } 187 | 188 | return $list; 189 | } 190 | 191 | /** 192 | * @param string $path 193 | */ 194 | public function getMetadata($path) 195 | { 196 | return $this->client()->info($path); 197 | } 198 | 199 | /** 200 | * @param string $path 201 | */ 202 | public function getType($path) 203 | { 204 | $response = $this->getMetadata($path); 205 | 206 | return ['type' => $response['x-upyun-file-type']]; 207 | } 208 | 209 | /** 210 | * @param string $path 211 | */ 212 | public function getSize($path) 213 | { 214 | $response = $this->getMetadata($path); 215 | 216 | return ['size' => $response['x-upyun-file-size']]; 217 | } 218 | 219 | /** 220 | * @param string $path 221 | */ 222 | public function getMimetype($path) 223 | { 224 | $headers = get_headers($this->getUrl($path), 1); 225 | $mimetype = $headers['Content-Type']; 226 | return compact('mimetype'); 227 | } 228 | 229 | /** 230 | * @param string $path 231 | */ 232 | public function getTimestamp($path) 233 | { 234 | $response = $this->getMetadata($path); 235 | 236 | return ['timestamp' => $response['x-upyun-file-date']]; 237 | } 238 | 239 | /** 240 | * @param string $path 241 | */ 242 | public function getVisibility($path) 243 | { 244 | return true; 245 | } 246 | 247 | /** 248 | * @param $path 249 | * @return string 250 | */ 251 | public function getUrl($path) 252 | { 253 | return $this->normalizeHost($this->domain).$path; 254 | } 255 | 256 | /** 257 | * @return Upyun 258 | */ 259 | protected function client() 260 | { 261 | $config = new \Upyun\Config($this->bucket, $this->operator, $this->password); 262 | $config->useSsl = config('filesystems.disks.upyun.protocol') === 'https' ? true : false; 263 | return new Upyun($config); 264 | } 265 | 266 | /** 267 | * Normalize the file info. 268 | * 269 | * @param array $stats 270 | * @param string $directory 271 | * 272 | * @return array 273 | */ 274 | protected function normalizeFileInfo(array $stats, string $directory) 275 | { 276 | $filePath = ltrim($directory . '/' . $stats['name'], '/'); 277 | 278 | return [ 279 | 'type' => $this->getType($filePath)['type'], 280 | 'path' => $filePath, 281 | 'timestamp' => $stats['time'], 282 | 'size' => $stats['size'], 283 | ]; 284 | } 285 | 286 | /** 287 | * @param $domain 288 | * @return string 289 | */ 290 | protected function normalizeHost($domain) 291 | { 292 | if (0 !== stripos($domain, 'https://') && 0 !== stripos($domain, 'http://')) { 293 | $domain = $this->protocol."://{$domain}"; 294 | } 295 | 296 | return rtrim($domain, '/').'/'; 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /src/UpyunServiceProvider.php: -------------------------------------------------------------------------------- 1 | addPlugin(new ImagePreviewUrl()); 28 | 29 | return $filesystem; 30 | }); 31 | } 32 | 33 | /** 34 | * Register the application services. 35 | * 36 | * @return void 37 | */ 38 | public function register() 39 | { 40 | // 41 | } 42 | } 43 | --------------------------------------------------------------------------------