├── .gitignore
├── src
├── Plugins
│ ├── Qetag.php
│ ├── AvInfo.php
│ ├── ImageInfo.php
│ ├── ImageExif.php
│ ├── LastReturn.php
│ ├── Fetch.php
│ ├── PersistentStatus.php
│ ├── WithUploadToken.php
│ ├── ImagePreviewUrl.php
│ ├── UploadToken.php
│ ├── PrivateImagePreviewUrl.php
│ ├── PersistentFop.php
│ ├── DownloadUrl.php
│ ├── VerifyCallback.php
│ └── PrivateDownloadUrl.php
├── QiniuFilesystemServiceProvider.php
├── QiniuUrl.php
├── QiniuStorage.php
└── QiniuAdapter.php
├── composer.json
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.phar
2 | *.zip
3 | build/artifacts
4 | phpunit.xml
5 | phpunit.functional.xml
6 | .DS_Store
7 | .swp
8 | .build
9 | composer.lock
10 | vendor
11 | src/package.xml
12 | .idea/
13 |
--------------------------------------------------------------------------------
/src/Plugins/Qetag.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->qetag();
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class Qetag extends AbstractPlugin
21 | {
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'qetag';
30 | }
31 |
32 | public function handle($path = null)
33 | {
34 | return $this->filesystem->getAdapter()->getLastQetag();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Plugins/AvInfo.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->avInfo('filename.mp3');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class AvInfo extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'avInfo';
30 | }
31 |
32 | public function handle($path = null)
33 | {
34 | return $this->filesystem->getAdapter()->avInfo($path);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Plugins/ImageInfo.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->imageInfo('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class ImageInfo extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'imageInfo';
30 | }
31 |
32 | public function handle($path = null)
33 | {
34 | return $this->filesystem->getAdapter()->imageInfo($path);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Plugins/ImageExif.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->imageExif('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class ImageExif extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'imageExif';
30 | }
31 |
32 | public function handle($path = null)
33 | {
34 | return $this->filesystem->getAdapter()->imageExif($path);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Plugins/LastReturn.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->lastReturn();
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class LastReturn extends AbstractPlugin
21 | {
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'lastReturn';
30 | }
31 |
32 | public function handle($path = null)
33 | {
34 | return $this->filesystem->getAdapter()->getLastReturn();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Plugins/Fetch.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->fetch('http://abc.com/foo.jpg', 'bar.jpg');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class Fetch extends AbstractPlugin
21 | {
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'fetch';
30 | }
31 |
32 | public function handle($url, $key)
33 | {
34 | return $this->filesystem->getAdapter()->fetch($url, $key);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Plugins/PersistentStatus.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->persistentStatus('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class PersistentStatus extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'persistentStatus';
30 | }
31 |
32 | public function handle($id)
33 | {
34 | return $this->filesystem->getAdapter()->persistentStatus($id);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Plugins/WithUploadToken.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->withUploadToken($token);
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class WithUploadToken extends AbstractPlugin
21 | {
22 |
23 | /**
24 | * Get the method name.
25 | *
26 | * @return string
27 | */
28 | public function getMethod()
29 | {
30 | return 'withUploadToken';
31 | }
32 |
33 | public function handle($token)
34 | {
35 | $this->filesystem->getAdapter()->withUploadToken($token);
36 | }
37 | }
--------------------------------------------------------------------------------
/src/Plugins/ImagePreviewUrl.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->imagePreviewUrl('foo/bar1.css',$ops);
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class ImagePreviewUrl extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'imagePreviewUrl';
30 | }
31 |
32 | public function handle($path = null, $ops = null)
33 | {
34 | return $this->filesystem->getAdapter()->imagePreviewUrl($path, $ops);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Plugins/UploadToken.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->uploadToken('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class UploadToken extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'uploadToken';
30 | }
31 |
32 | public function handle($path = null, $expires = 3600, $policy = null, $strictPolicy = true)
33 | {
34 | return $this->filesystem->getAdapter()->uploadToken($path, $expires, $policy, $strictPolicy);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Plugins/PrivateImagePreviewUrl.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->privateImagePreviewUrl('foo/bar1.css',$ops);
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class PrivateImagePreviewUrl extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'privateImagePreviewUrl';
30 | }
31 |
32 | public function handle($path = null, $ops = null)
33 | {
34 | return $this->filesystem->getAdapter()->privateImagePreviewUrl($path, $ops);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Plugins/PersistentFop.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->persistentFop('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class PersistentFop extends AbstractPlugin {
21 |
22 | /**
23 | * Get the method name.
24 | *
25 | * @return string
26 | */
27 | public function getMethod()
28 | {
29 | return 'persistentFop';
30 | }
31 |
32 | public function handle($path = null, $fops = null, $pipline = null, $force = false, $notify_url = null)
33 | {
34 | return $this->filesystem->getAdapter()->persistentFop($path, $fops, $pipline, $force, $notify_url);
35 | }
36 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zgldh/qiniu-laravel-storage",
3 | "type": "library",
4 | "description": "Qiniu Resource (Cloud) Storage SDK for Laravel 5/6/7/8/9",
5 | "keywords": [
6 | "qiniu",
7 | "storage",
8 | "sdk",
9 | "cloud",
10 | "laravel"
11 | ],
12 | "license": "MIT",
13 | "authors": [
14 | {
15 | "name": "zgldh",
16 | "email": "zgldh@hotmail.com",
17 | "role": "Original Developer"
18 | },
19 | {
20 | "name": "abcsun",
21 | "email": "chenglongsun_nj@163.com",
22 | "role": "Developer",
23 | "homepage": "http://github.com/abcsun"
24 | }
25 | ],
26 | "require": {
27 | "php": ">=5.3.3",
28 | "qiniu/php-sdk": "^7.2",
29 | "league/flysystem": "^3.0"
30 | },
31 | "autoload": {
32 | "psr-4": {
33 | "zgldh\\QiniuStorage\\": "src/"
34 | }
35 | },
36 | "extra": {
37 | "laravel": {
38 | "providers": [
39 | "zgldh\\QiniuStorage\\QiniuFilesystemServiceProvider"
40 | ]
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Plugins/DownloadUrl.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->downloadUrl('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class DownloadUrl extends AbstractPlugin
21 | {
22 |
23 | /**
24 | * Get the method name.
25 | *
26 | * @return string
27 | */
28 | public function getMethod()
29 | {
30 | return 'downloadUrl';
31 | }
32 |
33 | public function handle($path = null, $domainType = 'default')
34 | {
35 | $adapter = $this->filesystem->getAdapter();
36 | return $adapter->downloadUrl($path, $domainType);
37 | }
38 | }
--------------------------------------------------------------------------------
/src/Plugins/VerifyCallback.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->verifyCallback('application/x-www-form-urlencoded', $request->header('Authorization'), 'callback url', $request->getContent());
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class VerifyCallback extends AbstractPlugin
21 | {
22 |
23 | /**
24 | * Get the method name.
25 | *
26 | * @return string
27 | */
28 | public function getMethod()
29 | {
30 | return 'verifyCallback';
31 | }
32 |
33 | public function handle($contentType = null, $originAuthorization = null, $url = null, $body = null)
34 | {
35 | return $this->filesystem->getAdapter()->verifyCallback($contentType, $originAuthorization, $url, $body);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Plugins/PrivateDownloadUrl.php:
--------------------------------------------------------------------------------
1 |
16 | * $disk = \Storage::disk('qiniu');
17 | * $re = $disk->getDriver()->privateDownloadUrl('foo/bar1.css');
18 | * @package zgldh\QiniuStorage\Plugins
19 | */
20 | class PrivateDownloadUrl extends AbstractPlugin
21 | {
22 |
23 | /**
24 | * Get the method name.
25 | *
26 | * @return string
27 | */
28 | public function getMethod()
29 | {
30 | return 'privateDownloadUrl';
31 | }
32 |
33 | public function handle($path = null, $settings = 'default')
34 | {
35 | $adapter = $this->filesystem->getAdapter();
36 | return $adapter->privateDownloadUrl($path, $settings);
37 | }
38 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
21 |
--------------------------------------------------------------------------------
/src/QiniuFilesystemServiceProvider.php:
--------------------------------------------------------------------------------
1 | $config['domain'],
36 | 'https' => null,
37 | 'custom' => null
38 | ];
39 | }
40 | $qiniu_adapter = new QiniuAdapter(
41 | $config['access_key'],
42 | $config['secret_key'],
43 | $config['bucket'],
44 | $domains,
45 | isset($config['notify_url']) ? $config['notify_url'] : null,
46 | isset($config['access']) ? $config['access'] : 'public',
47 | isset($config['hotlink_prevention_key']) ? $config['hotlink_prevention_key'] : null
48 | );
49 | $file_system = new Filesystem($qiniu_adapter);
50 |
51 | return new FilesystemAdapter($file_system, $qiniu_adapter, $config);
52 | }
53 | );
54 | }
55 |
56 | public function register()
57 | {
58 | //
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/QiniuUrl.php:
--------------------------------------------------------------------------------
1 | url = $url;
14 | $this->hotPreventionKey = $hotPreventionKey;
15 | }
16 |
17 | public function __toString()
18 | {
19 | $url = trim($this->getUrl(), '?&');
20 |
21 | $parameters = $this->getParameters();
22 |
23 | if ($this->isHotlinkPrevention()) {
24 | list($sign, $t) = $this->hotlinkPreventionSign();
25 | $parameters[] = 'sign=' . $sign;
26 | $parameters[] = 't=' . $t;
27 | }
28 | $parameterString = join('&', $parameters);
29 |
30 | if ($parameterString) {
31 | if (strrpos($url, '?') === false) {
32 | $url .= '?' . $parameterString;
33 | } else {
34 | $url .= '&' . $parameterString;
35 | }
36 | }
37 | if (is_string($url) === false) {
38 | return '';
39 | }
40 | return $url;
41 | }
42 |
43 | /**
44 | * @return null
45 | */
46 | public function getUrl()
47 | {
48 | return $this->url;
49 | }
50 |
51 | /**
52 | * @param null $url
53 | */
54 | public function setUrl($url)
55 | {
56 | $this->url = $url;
57 | }
58 |
59 | /**
60 | * @return null
61 | */
62 | public function getDownload()
63 | {
64 | return $this->getParameter('download');
65 | }
66 |
67 | /**
68 | * @param null $download
69 | * @return QiniuUrl
70 | */
71 | public function setDownload($download)
72 | {
73 | return $this->setParameter('download', urlencode($download));
74 | }
75 |
76 | /**
77 | * @return array
78 | */
79 | public function getParameter($name)
80 | {
81 | return $this->parameters[$name];
82 | }
83 |
84 | /**
85 | * @return array
86 | */
87 | public function getParameters()
88 | {
89 | return $this->parameters;
90 | }
91 |
92 | /**
93 | * @param $name
94 | * @param $value
95 | * @return QiniuUrl
96 | */
97 | public function setParameter($name, $value)
98 | {
99 | $this->parameters[$name] = $name . '/' . $value;
100 | return $this;
101 | }
102 |
103 | /**
104 | * Specify data which should be serialized to JSON
105 | * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
106 | * @return mixed data which can be serialized by json_encode,
107 | * which is a value of any type other than a resource.
108 | * @since 5.4.0
109 | */
110 | function jsonSerialize()
111 | {
112 | return $this->__toString();
113 | }
114 |
115 | private function hotlinkPreventionSign()
116 | {
117 | $t = dechex(time() + 3600);
118 | $parsedUrl = parse_url($this->url);
119 | $pendingString = $this->getHotPreventionKey() . str_replace('%2F', '/', urlencode($parsedUrl['path'])) . $t;
120 | $sign = strtolower(md5($pendingString));
121 | return [$sign, $t];
122 | }
123 |
124 | /**
125 | * @return bool
126 | */
127 | public function isHotlinkPrevention()
128 | {
129 | return !!$this->getHotPreventionKey();
130 | }
131 |
132 | /**
133 | * @return null
134 | */
135 | public function getHotPreventionKey()
136 | {
137 | return $this->hotPreventionKey;
138 | }
139 |
140 | /**
141 | * @param null $hotPreventionKey
142 | */
143 | public function setHotPreventionKey($hotPreventionKey)
144 | {
145 | $this->hotPreventionKey = $hotPreventionKey;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/QiniuStorage.php:
--------------------------------------------------------------------------------
1 | storage = \Storage::disk($name);
21 | }
22 |
23 | /**
24 | * 文件是否存在
25 | * @param $key
26 | * @return bool
27 | */
28 | public function exists($key)
29 | {
30 | return $this->storage->exists($key);
31 | }
32 |
33 | /**
34 | * 获取文件内容
35 | * @param $key
36 | * @return string
37 | */
38 | public function get($key)
39 | {
40 | return $this->storage->get($key);
41 | }
42 |
43 | /**
44 | * 上传文件
45 | * @param $key
46 | * @param $contents
47 | * @return bool
48 | */
49 | public function put($key, $contents)
50 | {
51 | return $this->storage->put($key, $contents);
52 | }
53 |
54 | /**
55 | * 附加内容到文件开头
56 | * @param $key
57 | * @param $contents
58 | * @return int
59 | */
60 | public function prepend($key, $contents)
61 | {
62 | return $this->storage->prepend($key, $contents);
63 | }
64 |
65 | /**
66 | * 附加内容到文件结尾
67 | * @param $key
68 | * @param $content
69 | * @return int
70 | */
71 | public function append($key, $contents)
72 | {
73 | return $this->storage->append($key, $contents);
74 | }
75 |
76 | /**
77 | * 删除文件
78 | * @param $key
79 | * @return bool
80 | */
81 | public function delete($key)
82 | {
83 | return $this->storage->delete($key);
84 |
85 | }
86 |
87 | /**
88 | * 复制文件到新的路径
89 | * @param $key
90 | * @param $key2
91 | * @return bool
92 | */
93 | public function copy($key, $key2)
94 | {
95 | return $this->storage->copy($key, $key2);
96 |
97 | }
98 |
99 | /**
100 | * 移动文件到新的路径
101 | * @param $key
102 | * @param $key2
103 | * @return bool
104 | */
105 | public function move($key, $key2)
106 | {
107 | return $this->storage->move($key, $key2);
108 |
109 | }
110 |
111 | public function size($key)
112 | {
113 | return $this->storage->size($key);
114 |
115 | }
116 |
117 | public function lastModified($key)
118 | {
119 | return $this->storage->lastModified($key);
120 |
121 | }
122 |
123 | public function files($key)
124 | {
125 | return $this->storage->files($key);
126 | }
127 |
128 | public function allFiles($key)
129 | {
130 | return $this->storage->files($key);
131 | }
132 |
133 | public function directories($key)
134 | {
135 | return $this->storage->files($key);
136 | }
137 |
138 | public function allDirectories($key)
139 | {
140 | return $this->storage->files($key);
141 | }
142 |
143 | public function makeDirectory($key)
144 | {
145 | return $this->storage->makeDirectory($key);
146 | }
147 |
148 | public function deleteDirectory($key)
149 | {
150 | return $this->storage->deleteDirectory($key);
151 | }
152 |
153 | /**
154 | * 获取上传Token
155 | * @param $key
156 | * @param $expires
157 | * @param $policy
158 | * @param $strictPolicy
159 | * @return bool
160 | */
161 | public function uploadToken($key = null, $expires = 3600, $policy = null, $strictPolicy = true)
162 | {
163 | return $this->storage->getAdapter()->uploadToken($key, $expires, $policy, $strictPolicy);
164 | }
165 |
166 | /**
167 | * 下次 put 操作,将使用该 uploadToken 进行上传。 常用于持久化操作。
168 | * @param $token
169 | * @return mixed
170 | */
171 | public function withUploadToken($token)
172 | {
173 | $this->storage->getAdapter()->withUploadToken($token);
174 | }
175 |
176 | /**
177 | * 获取下载地址
178 | * @param $key
179 | * @return mixed
180 | */
181 | public function downloadUrl($key, $domainType = 'default')
182 | {
183 | return $this->storage->getAdapter()->downloadUrl($key, $domainType);
184 | }
185 |
186 | /**
187 | * 获取私有bucket下载地址
188 | * @param $key
189 | * @return mixed
190 | */
191 | public function privateDownloadUrl($key, $domainType = 'default')
192 | {
193 | return $this->storage->getAdapter()->privateDownloadUrl($key, $domainType);
194 | }
195 |
196 | /**
197 | * 获取多媒体文件信息
198 | * @param $key
199 | * @return mixed
200 | */
201 | public function avInfo($key)
202 | {
203 | return $this->storage->getAdapter()->avInfo($key);
204 | }
205 |
206 | /**
207 | * 获取图片信息
208 | * @param $key
209 | * @return mixed
210 | */
211 | public function imageInfo($key)
212 | {
213 | return $this->storage->getAdapter()->imageInfo($key);
214 | }
215 |
216 | /**
217 | * 获取图片EXIF信息
218 | * @param $key
219 | * @return mixed
220 | */
221 | public function imageExif($key)
222 | {
223 | return $this->storage->getAdapter()->imageExif($key);
224 | }
225 |
226 | /**
227 | * 获取图片预览URL
228 | * @param $key
229 | * @param $opts
230 | * @return mixed
231 | */
232 | public function imagePreviewUrl($key, $opts)
233 | {
234 | return $this->storage->getAdapter()->imagePreviewUrl($key, $opts);
235 | }
236 |
237 | /**
238 | * 获取私有bucket图片预览URL
239 | * @param $key
240 | * @param $opts
241 | * @return mixed
242 | */
243 | public function privateImagePreviewUrl($key, $opts)
244 | {
245 | return $this->storage->getAdapter()->privateImagePreviewUrl($key, $opts);
246 | }
247 |
248 | /**
249 | * 执行持久化数据处理
250 | * @param $key
251 | * @param $opts
252 | * @param $pipline
253 | * @param $force
254 | * @param $notify_url
255 | * @return mixed
256 | */
257 | public function persistentFop($key, $opts, $pipline = null, $force = false, $notify_url = null)
258 | {
259 | return $this->storage->getAdapter()->persistentFop($key, $opts, $pipline, $force, $notify_url);
260 | }
261 |
262 | /**
263 | * 查看持久化数据处理的状态
264 | * @param $id
265 | * @return mixed
266 | */
267 | public function persistentStatus($id)
268 | {
269 | return $this->storage->getAdapter()->persistentStatus($id);
270 | }
271 |
272 | /**
273 | * 验证回调是否合法
274 | * @param $id
275 | * @return boolean
276 | */
277 | public function verifyCallback($contentType, $originAuthorization, $url, $body)
278 | {
279 | return $this->storage->getAdapter()->verifyCallback($contentType, $originAuthorization, $url, $body);
280 | }
281 |
282 | /**
283 | * 调用fetch将 foo.jpg 数据以 bar.jpg 的名字储存起来。
284 | * @param $url
285 | * @param $key
286 | * @return bool
287 | */
288 | public function fetch($url, $key)
289 | {
290 | return $this->storage->getAdapter()->fetch($url, $key);
291 | }
292 |
293 | /**
294 | * 得到最后一次执行 put, copy, append 等写入操作后,得到的hash值。详见 https://github.com/qiniu/qetag
295 | * @return string
296 | */
297 | public function qetag()
298 | {
299 | return $this->storage->getAdapter()->qetag();
300 | }
301 |
302 | /**
303 | * 得到最后一次执行 put, copy, append 等写入操作后,得到的返回值。
304 | * @return array
305 | */
306 | public function lastReturn()
307 | {
308 | return $this->storage->getAdapter()->getLastReturn();
309 | }
310 | }
311 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Qiniu 云储存 Laravel 5/6/7/8/9 Storage版
2 |
3 | 基于 https://github.com/qiniu/php-sdk 开发
4 |
5 | 符合Laravel 5/6/7/8/9 的Storage用法。
6 |
7 | ## 注意
8 |
9 | 从七牛获取到的`putTime`时间戳,是以 100纳秒 为单位的。
10 |
11 | 参考 https://developer.qiniu.com/kodo/api/1308/stat https://developer.qiniu.com/kodo/api/1284/list
12 |
13 | PHP 可以用 [Carbon](http://carbon.nesbot.com/docs/) `Carbon::createFromTimestampMs($putTime/10000)` 来保证最大精度
14 |
15 |
16 | JavaScript 可以用 [moment](http://momentjs.cn/docs/#/parsing/unix-offset/) `moment(putTime/10000)` 来保证最大精度
17 |
18 |
19 | ## 更新
20 |
21 | v9.0
22 | 支持 Laravel 9
23 |
24 | v0.10
25 | 支持“公开空间”的 CDN 时间戳防盗链
26 |
27 | v0.9
28 | 兼容 Laravel 5.5 的自动包安装功能
29 |
30 | v0.8
31 | 1. 修正了getUrl
32 | 2. 修正了最新的 Qiniu API 适配
33 |
34 | v0.7
35 | 1. 增加了 ```withUploadToken```, ```lastReturn``` 等命令。
36 | 2. 修正了代码内的一些typo
37 |
38 | v0.6 增加了```fetch```, ```qetag``` 命令。
39 |
40 | v0.5 增加了```QiniuUrl```来更方便的设置文件 URL 参数。
41 |
42 | v0.3 增加了对PIPE以及回调地址参数的配置。 感谢abcsun提供的灵感。
43 |
44 | v0.2 提供了对多域名的支持。这是为了配合七牛的默认域名、HTTPS域名和自定义域名而添加的功能。
45 |
46 | ## 安装
47 |
48 | - ```composer require zgldh/qiniu-laravel-storage:0.10.3```
49 | - ```config/app.php``` 里面的 ```providers``` 数组, 加上一行 ```zgldh\QiniuStorage\QiniuFilesystemServiceProvider::class```
50 | - ```config/filesystem.php``` 里面的 ```disks```数组加上:
51 |
52 | ```php
53 |
54 | 'disks' => [
55 | ... ,
56 | 'qiniu' => [
57 | 'driver' => 'qiniu',
58 | 'domains' => [
59 | 'default' => 'xxxxx.com1.z0.glb.clouddn.com', //你的七牛域名
60 | 'https' => 'dn-yourdomain.qbox.me', //你的HTTPS域名
61 | 'custom' => 'static.abc.com', //Useless 没啥用,请直接使用上面的 default 项
62 | ],
63 | 'access_key'=> '', //AccessKey
64 | 'secret_key'=> '', //SecretKey
65 | 'bucket' => '', //Bucket名字
66 | 'notify_url'=> '', //持久化处理回调地址
67 | 'access' => 'public', //空间访问控制 public 或 private
68 | 'hotlink_prevention_key' => 'afc89ff8bd2axxxxxxxxxxxxxxbb', // CDN 时间戳防盗链的 key。 设置为 null 则不启用本功能。
69 | // 'hotlink_prevention_key' => 'cbab68a279xxxxxxxxxxab509a', // 同上,备用
70 | ],
71 | ],
72 |
73 | ```
74 |
75 | - 完成
76 |
77 | ## 使用
78 |
79 | 第一种用法
80 |
81 | ```php
82 |
83 | $disk = \Storage::disk('qiniu');
84 | $disk->exists('file.jpg'); //文件是否存在
85 | $disk->get('file.jpg'); //获取文件内容
86 | $disk->put('file.jpg',$contents); //上传文件
87 | $disk->put('file.jpg',fopen('path/to/big.jpg','r+')); //分段上传文件。建议大文件>10Mb使用。
88 | $disk->prepend('file.log', 'Prepended Text'); //附加内容到文件开头
89 | $disk->append('file.log', 'Appended Text'); //附加内容到文件结尾
90 | $disk->delete('file.jpg'); //删除文件
91 | $disk->delete(['file1.jpg', 'file2.jpg']);
92 | $disk->copy('old/file1.jpg', 'new/file1.jpg'); //复制文件到新的路径
93 | $disk->move('old/file1.jpg', 'new/file1.jpg'); //移动文件到新的路径
94 | $size = $disk->size('file1.jpg'); //取得文件大小
95 | $time = $disk->lastModified('file1.jpg'); //取得最近修改时间 (UNIX)
96 | $files = $disk->files($directory); //取得目录下所有文件
97 | $files = $disk->allFiles($directory); //这个没实现。。。
98 | $directories = $disk->directories($directory); //这个也没实现。。。
99 | $directories = $disk->allDirectories($directory); //这个也没实现。。。
100 | $disk->makeDirectory($directory); //这个其实没有任何作用
101 | $disk->deleteDirectory($directory); //删除目录,包括目录下所有子文件子目录
102 | $disk->url('a.png'); //返回文件的URL
103 | $disk->url(['path' => 'a.png', 'domainType' => 'default']); //返回文件的URL
104 |
105 | $disk->getAdapter()->uploadToken(); //获取上传Token
106 | $disk->getAdapter()->uploadToken('file.jpg'); //获取上传Token
107 |
108 | $disk->getAdapter()->withUploadToken($token); // 使用自定义的 uploadToken 进行上传,
109 | $disk->put('file.jpg',$content); // 则本次的 put 操作,将使用上述的 $token 进行上传。
110 | // 常用于自动触发持久化处理 https://github.com/qiniu/php-sdk/blob/master/examples/upload_and_pfop.php
111 |
112 | $disk->getAdapter()->downloadUrl('file.jpg'); //获取下载地址
113 | $disk->getAdapter()->downloadUrl('file.jpg')
114 | ->setDownload('foo.jpg'); //获取下载地址,文件名为 foo.jpg
115 | $disk->getAdapter()->downloadUrl('file.jpg', 'https'); //获取HTTPS下载地址
116 | $disk->getAdapter()->privateDownloadUrl('file.jpg'); //获取私有bucket下载地址
117 | $disk->getAdapter()->privateDownloadUrl('file.jpg?attname=foo.jpg');
118 | //获取私有bucket下载地址,文件名为 foo.jpg
119 | $disk->getAdapter()->privateDownloadUrl('file.jpg', 'https');//获取私有bucket的HTTPS下载地址
120 | $disk->getAdapter()->privateDownloadUrl('file.jpg',
121 | [
122 | 'domain'=>'https',
123 | 'expires'=>3600
124 | ]); //获取私有bucket的HTTPS下载地址。超时 3600 秒。
125 | $disk->getAdapter()->avInfo('file.mp3'); //获取多媒体文件信息
126 | $disk->getAdapter()->imageInfo('file.jpg'); //获取图片信息
127 | $disk->getAdapter()->imageExif('file.jpg'); //获取图片EXIF信息
128 | $disk->getAdapter()->imagePreviewUrl('file.jpg','imageView2/0/w/100/h/200'); //获取图片预览URL
129 | $disk->getAdapter()->privateImagePreviewUrl('file.jpg','imageView2/0/w/100/h/200'); //获取私有bucket图片预览URL
130 | $disk->getAdapter()->verifyCallback('application/x-www-form-urlencoded', $request->header('Authorization'), 'callback url', $request->getContent());//验证回调内容是否合法
131 | $disk->getAdapter()->persistentFop('file.flv','avthumb/m3u8/segtime/40/vcodec/libx264/s/320x240'); //执行持久化数据处理
132 | $disk->getAdapter()->persistentFop('file.flv','fop','队列名'); //使用私有队列执行持久化数据处理
133 | $disk->getAdapter()->persistentStatus($persistent_fop_id); //查看持久化数据处理的状态。
134 | $disk->getAdapter()->fetch('http://abc.com/foo.jpg', 'bar.jpg'); //调用fetch将 foo.jpg 数据以 bar.jpg 的名字储存起来。
135 | $disk->getAdapter()->qetag(); //得到最后一次执行 put, copy, append 等写入操作后,得到的hash值。详见 https://github.com/qiniu/qetag
136 | $disk->getAdapter()->lastReturn(); //得到最后一次执行 put, copy, append 等写入操作后,得到的返回值。
137 |
138 | ```
139 |
140 | 第二种用法 (就是省略了一个getAdapter)
141 |
142 | ```php
143 |
144 | use zgldh\QiniuStorage\QiniuStorage;
145 |
146 | $disk = QiniuStorage::disk('qiniu');
147 | $disk->exists('file.jpg'); //文件是否存在
148 | $disk->get('file.jpg'); //获取文件内容
149 | $disk->put('file.jpg',$contents); //上传文件
150 | $disk->put('file.jpg',fopen('path/to/big.jpg','r+')); //分段上传文件。建议大文件>10Mb使用。
151 | $disk->prepend('file.log', 'Prepended Text'); //附加内容到文件开头
152 | $disk->append('file.log', 'Appended Text'); //附加内容到文件结尾
153 | $disk->delete('file.jpg'); //删除文件
154 | $disk->delete(['file1.jpg', 'file2.jpg']);
155 | $disk->copy('old/file1.jpg', 'new/file1.jpg'); //复制文件到新的路径
156 | $disk->move('old/file1.jpg', 'new/file1.jpg'); //移动文件到新的路径
157 | $size = $disk->size('file1.jpg'); //取得文件大小
158 | $time = $disk->lastModified('file1.jpg'); //取得最近修改时间 (UNIX)
159 | $files = $disk->files($directory); //取得目录下所有文件
160 | $files = $disk->allFiles($directory); //这个没实现。。。
161 | $directories = $disk->directories($directory); //这个也没实现。。。
162 | $directories = $disk->allDirectories($directory); //这个也没实现。。。
163 | $disk->makeDirectory($directory); //这个其实没有任何作用
164 | $disk->deleteDirectory($directory); //删除目录,包括目录下所有子文件子目录
165 |
166 | $disk->uploadToken(); //获取上传Token
167 | $disk->uploadToken('file.jpg'); //获取上传Token
168 |
169 | $disk->withUploadToken($token); // 使用自定义的 uploadToken 进行上传,
170 | $disk->put('file.jpg',$content); // 则本次的 put 操作,将使用上述的 $token 进行上传。
171 | // 常用于自动触发持久化处理 https://github.com/qiniu/php-sdk/blob/master/examples/upload_and_pfop.php
172 |
173 | $disk->downloadUrl('file.jpg'); //获取下载地址
174 | $disk->downloadUrl('file.jpg')
175 | ->setDownload('foo.jpg'); //获取下载地址,文件名为 foo.jpg
176 | $disk->downloadUrl('file.jpg', 'https'); //获取HTTPS下载地址
177 | $disk->privateDownloadUrl('file.jpg'); //获取私有bucket下载地址
178 | $disk->privateDownloadUrl('file.jpg?attname=foo.jpg');
179 | //获取私有bucket下载地址,文件名为 foo.jpg
180 | $disk->privateDownloadUrl('file.jpg', 'https'); //获取私有bucket的HTTPS下载地址
181 | $disk->privateDownloadUrl('file.jpg',
182 | [
183 | 'domain'=>'https',
184 | 'expires'=>3600
185 | ]); //获取私有bucket的HTTPS下载地址。超时 3600 秒。
186 | $disk->avInfo('file.mp3'); //获取多媒体文件信息
187 | $disk->imageInfo('file.jpg'); //获取图片信息
188 | $disk->imageExif('file.jpg'); //获取图片EXIF信息
189 | $disk->imagePreviewUrl('file.jpg','imageView2/0/w/100/h/200'); //获取图片预览URL
190 | $disk->privateImagePreviewUrl('file.jpg','imageView2/0/w/100/h/200'); //获取私有bucket图片预览URL
191 | $disk->verifyCallback('application/x-www-form-urlencoded', $request->header('Authorization'), 'callback url', $request->getContent());//验证回调内容是否合法
192 | $disk->persistentFop('file.flv','avthumb/m3u8/segtime/40/vcodec/libx264/s/320x240'); //执行持久化数据处理
193 | $disk->persistentFop('file.flv','fop','队列名'); //使用私有队列执行持久化数据处理
194 | $disk->persistentStatus($persistent_fop_id); //查看持久化数据处理的状态。
195 |
196 | $disk->fetch('http://abc.com/foo.jpg', 'bar.jpg'); //调用fetch将 foo.jpg 数据以 bar.jpg 的名字储存起来。
197 | $disk->qetag(); //得到最后一次执行 put, copy, append 等写入操作后,得到的hash值。详见 https://github.com/qiniu/qetag
198 | $disk->lastReturn();//得到最后一次执行 put, copy, append 等写入操作后,得到的返回值。
199 |
200 | ```
201 |
202 |
203 | ## 官方SDK / 手册
204 |
205 | - https://github.com/qiniu/php-sdk
206 | - http://developer.qiniu.com/docs/v6/sdk/php-sdk.html
207 |
208 |
209 |
--------------------------------------------------------------------------------
/src/QiniuAdapter.php:
--------------------------------------------------------------------------------
1 | access_key = $access_key;
62 | $this->secret_key = $secret_key;
63 | $this->bucket = $bucket;
64 | $this->domains = $domains;
65 | $this->setPathPrefix('http://' . $this->domains['default']);
66 | $this->setDomainPrefix('http://' . $this->domains['default'], 'default');
67 | $this->setDomainPrefix('https://' . $this->domains['https'], 'https');
68 | $this->setDomainPrefix('http://' . $this->domains['custom'], 'custom');
69 | $this->notify_url = $notify_url;
70 | $this->access = $access;
71 | $this->hotlinkPreventionKey = $hotlinkPreventionKey;
72 | }
73 |
74 | /**
75 | * Set the path prefix.
76 | *
77 | * @param string $prefix
78 | *
79 | * @return self
80 | */
81 | public function setDomainPrefix($prefix, $domainType)
82 | {
83 | $is_empty = empty($prefix);
84 |
85 | if (!$is_empty) {
86 | $prefix = rtrim($prefix, $this->pathSeparator) . $this->pathSeparator;
87 | }
88 |
89 | $prefixedDomain = $is_empty ? null : $prefix;
90 | $this->prefixedDomains[$domainType] = $prefixedDomain;
91 | }
92 |
93 | public function withUploadToken($token)
94 | {
95 | $this->uploadToken = $token;
96 | }
97 |
98 | private function getAuth()
99 | {
100 | if ($this->auth == null) {
101 | $this->auth = new Auth($this->access_key, $this->secret_key);
102 | }
103 |
104 | return $this->auth;
105 | }
106 |
107 | private function getUploadManager()
108 | {
109 | if ($this->upload_manager == null) {
110 | $this->upload_manager = new UploadManager();
111 | }
112 |
113 | return $this->upload_manager;
114 | }
115 |
116 | private function getBucketManager()
117 | {
118 | if ($this->bucket_manager == null) {
119 | $this->bucket_manager = new BucketManager($this->getAuth());
120 | }
121 |
122 | return $this->bucket_manager;
123 | }
124 |
125 | private function getOperation()
126 | {
127 | if ($this->operation == null) {
128 | $this->operation = new Operation(
129 | $this->domains['default'],
130 | $this->access === self::ACCESS_PUBLIC ? null : $this->getAuth()
131 | );
132 | }
133 |
134 | return $this->operation;
135 | }
136 |
137 | private function logQiniuError(Error $error, $extra = null)
138 | {
139 | \Log::error('Qiniu: ' . $error->code() . ' ' . $error->message() . '. ' . $extra);
140 | }
141 |
142 | /**
143 | * Update a file.
144 | *
145 | * @param string $path
146 | * @param string $contents
147 | * @param Config $config Config object
148 | *
149 | * @return array|false false on failure file meta data on success
150 | */
151 | public function update($path, $contents, Config $config)
152 | {
153 | return $this->write($path, $contents, $config);
154 | }
155 |
156 | /**
157 | * Rewrite Qiniu\Storage\UploadManager::putFile
158 | * @param $upToken
159 | * @param $key
160 | * @param $fileResource
161 | * @param null $params
162 | * @param string $mime
163 | * @param bool $checkCrc
164 | * @return mixed
165 | * @throws \Exception
166 | */
167 | private function qiniuPutFile(
168 | $upToken,
169 | $key,
170 | $fileResource,
171 | $params = null,
172 | $mime = 'application/octet-stream',
173 | $checkCrc = false
174 | )
175 | {
176 | if ($fileResource === false) {
177 | throw new \Exception("file can not open", 1);
178 | }
179 | $file = $fileResource;
180 | $params = UploadManager::trimParams($params);
181 | $stat = fstat($file);
182 | $size = $stat['size'];
183 | if ($size <= QiniuConfig::BLOCK_SIZE) {
184 | $data = fread($file, $size);
185 | fclose($file);
186 | if ($data === false) {
187 | throw new \Exception("file can not read", 1);
188 | }
189 | $result = FormUploader::put(
190 | $upToken,
191 | $key,
192 | $data,
193 | new QiniuConfig(),
194 | $params,
195 | $mime,
196 | basename($key)
197 | );
198 | return $result;
199 | }
200 | $up = new ResumeUploader(
201 | $upToken,
202 | $key,
203 | $file,
204 | $size,
205 | $params,
206 | $mime,
207 | new QiniuConfig()
208 | );
209 | $ret = $up->upload(basename($key));
210 | fclose($file);
211 | return $ret;
212 | }
213 |
214 |
215 | /**
216 | * Fetch a file.
217 | *
218 | * @DriverFunction
219 | * @param string $url
220 | * @param string $key
221 | *
222 | * @return bool|array
223 | */
224 | public function fetch($url, $key = null)
225 | {
226 | $bucketMgr = $this->getBucketManager();
227 |
228 | [$ret, $error] = $bucketMgr->fetch($url, $this->bucket, $key);
229 | if ($error !== null) {
230 | $this->logQiniuError($error, $this->bucket . '/' . $key);
231 |
232 | return false;
233 | } else {
234 | return $ret;
235 | }
236 | }
237 |
238 | /**
239 | * Create a directory.
240 | *
241 | * @param string $dirname directory name
242 | * @param Config $config
243 | *
244 | * @return array|false
245 | */
246 | public function createDir($dirname, Config $config)
247 | {
248 | return ['path' => $dirname];
249 | }
250 |
251 |
252 | /**
253 | * Get all the meta data of a file or directory.
254 | *
255 | * @param string $path
256 | *
257 | * @return array|false
258 | */
259 | private function getMetadata($path)
260 | {
261 | $bucketMgr = $this->getBucketManager();
262 |
263 | [$ret, $error] = $bucketMgr->stat($this->bucket, $path);
264 | if ($error !== null) {
265 | return false;
266 | } else {
267 | return $ret;
268 | }
269 | }
270 |
271 | /**
272 | * @DriverFunction
273 | * @param null $path
274 | * @param string $domainType
275 | * @return string|QiniuUrl
276 | */
277 | public function downloadUrl($path = null, $domainType = 'default')
278 | {
279 | if ($this->access == self::ACCESS_PRIVATE) {
280 | return $this->privateDownloadUrl($path, $domainType);
281 | }
282 | $this->pathPrefix = $this->prefixedDomains[$domainType];
283 | $location = $this->applyPathPrefix($path);
284 | $location = new QiniuUrl($location, $this->hotlinkPreventionKey);
285 |
286 | return $location;
287 | }
288 |
289 | /**
290 | * @DriverFunction
291 | * @param mixed $path
292 | * @return string
293 | */
294 | public function getUrl($path)
295 | {
296 | if (is_string($path)) {
297 | return $this->downloadUrl($path, 'default')->getUrl();
298 | }
299 |
300 | if (is_array($path)) {
301 | return $this->downloadUrl($path['path'], $path['domainType'])->getUrl();
302 | }
303 |
304 | return $this->downloadUrl('', 'default')->getUrl();
305 |
306 | }
307 |
308 | /**
309 | * @DriverFunction
310 | * @param $path
311 | * @param string|array $settings ['domain'=>'default', 'expires'=>3600]
312 | * @return string
313 | */
314 | public function privateDownloadUrl($path, $settings = 'default')
315 | {
316 | $expires = 3600;
317 | $domain = 'default';
318 | if (is_array($settings)) {
319 | $expires = isset($settings['expires']) ? $settings['expires'] : $expires;
320 | $domain = isset($settings['domain']) ? $settings['domain'] : $domain;
321 | } else {
322 | $domain = $settings;
323 | }
324 | $this->pathPrefix = $this->prefixedDomains[$domain];
325 | $auth = $this->getAuth();
326 | $location = $this->applyPathPrefix($path);
327 | $authUrl = $auth->privateDownloadUrl($location, $expires);
328 | $authUrl = new QiniuUrl($authUrl);
329 |
330 | return $authUrl;
331 | }
332 |
333 | /**
334 | * @DriverFunction
335 | * @param null $path
336 | * @param null $fops
337 | * @param null $pipline
338 | * @param bool $force
339 | * @return bool
340 | */
341 | public function persistentFop($path = null, $fops = null, $pipline = null, $force = false, $notifyUrl = null)
342 | {
343 | $auth = $this->getAuth();
344 |
345 | $pfop = new PersistentFop($auth);
346 |
347 | $notifyUrl = is_null($notifyUrl) ? $this->notify_url : $notifyUrl;
348 | [$id, $error] = $pfop->execute($this->bucket, $path, $fops, $pipline, $notifyUrl, $force);
349 |
350 | if ($error != null) {
351 | $this->logQiniuError($error);
352 |
353 | return false;
354 | } else {
355 | return $id;
356 | }
357 | }
358 |
359 | /**
360 | * @DriverFunction
361 | * @param $id
362 | * @return array
363 | */
364 | public function persistentStatus($id)
365 | {
366 | $auth = $this->getAuth();
367 | $pfop = new PersistentFop($auth);
368 | return $pfop->status($id);
369 | }
370 |
371 | /**
372 | * @DriverFunction
373 | * @param null $path
374 | * @return bool
375 | */
376 | public function avInfo($path = null)
377 | {
378 | $operation = $this->getOperation();
379 |
380 | [$ret, $error] = $operation->execute($path, 'avinfo');
381 |
382 | if ($error !== null) {
383 | $this->logQiniuError($error);
384 |
385 | return false;
386 | } else {
387 | return $ret;
388 | }
389 | }
390 |
391 | /**
392 | * @DriverFunction
393 | * @param null $path
394 | * @return bool
395 | */
396 | public function imageInfo($path = null)
397 | {
398 | $operation = $this->getOperation();
399 |
400 | [$ret, $error] = $operation->execute($path, 'imageInfo');
401 |
402 | if ($error !== null) {
403 | $this->logQiniuError($error);
404 |
405 | return false;
406 | } else {
407 | return $ret;
408 | }
409 | }
410 |
411 | /**
412 | * @DriverFunction
413 | * @param null $path
414 | * @return bool
415 | */
416 | public function imageExif($path = null)
417 | {
418 | $operation = $this->getOperation();
419 |
420 | [$ret, $error] = $operation->execute($path, 'exif');
421 |
422 | if ($error !== null) {
423 | $this->logQiniuError($error);
424 |
425 | return false;
426 | } else {
427 | return $ret;
428 | }
429 | }
430 |
431 | /**
432 | * @DriverFunction
433 | * @param null $path
434 | * @param null $ops
435 | * @return string|QiniuUrl
436 | */
437 | public function imagePreviewUrl($path = null, $ops = null)
438 | {
439 | if ($this->access == self::ACCESS_PRIVATE) {
440 | return $this->privateImagePreviewUrl($path, $ops);
441 | }
442 | $operation = $this->getOperation();
443 | $url = $operation->buildUrl($path, $ops);
444 | $url = new QiniuUrl($url, $this->hotlinkPreventionKey);
445 |
446 | return $url;
447 | }
448 |
449 | /**
450 | * @DriverFunction
451 | * @param null $path
452 | * @param null $ops
453 | * @return string|QiniuUrl
454 | */
455 | public function privateImagePreviewUrl($path = null, $ops = null)
456 | {
457 | $auth = $this->getAuth();
458 | $operation = $this->getOperation();
459 | $url = $operation->buildUrl($path, $ops);
460 | $authUrl = $auth->privateDownloadUrl($url);
461 | $authUrl = new QiniuUrl($authUrl);
462 |
463 | return $authUrl;
464 | }
465 |
466 | /**
467 | * @DriverFunction
468 | * @param null $path
469 | * @param int $expires
470 | * @param null $policy
471 | * @param bool $strictPolicy
472 | * @return string
473 | */
474 | public function uploadToken(
475 | $path = null,
476 | $expires = 3600,
477 | $policy = null,
478 | $strictPolicy = true
479 | )
480 | {
481 | $auth = $this->getAuth();
482 |
483 | $token = $auth->uploadToken(
484 | $this->bucket,
485 | $path,
486 | $expires,
487 | $policy,
488 | $strictPolicy
489 | );
490 |
491 | return $token;
492 | }
493 |
494 | /**
495 | * @DriverFunction
496 | * @param $contentType
497 | * @param $originAuthorization
498 | * @param $url
499 | * @param $body
500 | * @return bool
501 | */
502 | public function verifyCallback($contentType, $originAuthorization, $url, $body)
503 | {
504 | $auth = $this->getAuth();
505 |
506 | return $auth->verifyCallback($contentType, $originAuthorization, $url, $body);
507 | }
508 |
509 | /**
510 | * @DriverFunction
511 | * @param $localFilePath
512 | * @return array
513 | */
514 | public function calculateQetag($localFilePath)
515 | {
516 | return Etag::sum($localFilePath);
517 | }
518 |
519 | /**
520 | * @DriverFunction
521 | * @return null
522 | */
523 | public function getLastQetag()
524 | {
525 | if ($this->lastReturn && isset($this->lastReturn['hash'])) {
526 | return $this->lastReturn['hash'];
527 | }
528 | return null;
529 | }
530 |
531 | /**
532 | * @DriverFunction
533 | * @return null
534 | */
535 | public function getLastReturn()
536 | {
537 | return $this->lastReturn;
538 | }
539 |
540 | /**
541 | * Write a new file.
542 | *
543 | * @param string $path
544 | * @param string $contents
545 | * @param Config $config Config object
546 | *
547 | * @return array|false false on failure file meta data on success
548 | */
549 | public function write(string $path, string $contents, Config $config): void
550 | {
551 | $auth = $this->getAuth();
552 |
553 | $token = $this->uploadToken ?: $auth->uploadToken($this->bucket, $path);
554 | $this->withUploadToken(null);
555 |
556 | $params = $config->get('params', null);
557 | $mime = $config->get('mime', 'application/octet-stream');
558 | $checkCrc = $config->get('checkCrc', false);
559 |
560 | $upload_manager = $this->getUploadManager();
561 | [$ret, $error] = $upload_manager->put($token, $path, $contents, $params, $mime, $checkCrc);
562 |
563 | if ($error !== null) {
564 | $this->logQiniuError($error);
565 | throw UnableToWriteFile::atLocation($path, $error->message());
566 | } else {
567 | $this->lastReturn = $ret;
568 | }
569 | }
570 |
571 | /**
572 | * Write using a stream.
573 | *
574 | * @param string $path
575 | * @param $contents
576 | * @param Config $config
577 | *
578 | * @return mixed false or file metadata
579 | * @throws \Exception
580 | */
581 | public function writeStream(string $path, $contents, Config $config): void
582 | {
583 | $auth = $this->getAuth();
584 |
585 | $token = $this->uploadToken ?: $auth->uploadToken($this->bucket, $path);
586 | $this->withUploadToken(null);
587 |
588 | $params = $config->get('params', null);
589 | $mime = $config->get('mime', 'application/octet-stream');
590 | $checkCrc = $config->get('checkCrc', false);
591 |
592 | [$ret, $error] = $this->qiniuPutFile($token, $path, $contents, $params, $mime, $checkCrc);
593 |
594 | if ($error !== null) {
595 | $this->logQiniuError($error);
596 | } else {
597 | $this->lastReturn = $ret;
598 | }
599 | }
600 |
601 | /**
602 | * Read a file.
603 | *
604 | * @param string $path
605 | *
606 | * @return array|false
607 | */
608 | public function read(string $path): string
609 | {
610 | $location = $this->applyPathPrefix($path);
611 | $content = file_get_contents($location);
612 | if (false === $content) {
613 | throw UnableToReadFile::fromLocation($path);
614 | }
615 | return $content;
616 | }
617 |
618 | public function readStream(string $path)
619 | {
620 | if (ini_get('allow_url_fopen')) {
621 | if ($result = fopen($this->getUrl($path), 'r')) {
622 | return $result;
623 | }
624 | }
625 |
626 | throw UnableToReadFile::fromLocation($path);
627 | }
628 |
629 |
630 | /**
631 | * List contents of a directory.
632 | *
633 | * @param string $path
634 | * @param bool $deep
635 | * @return array
636 | */
637 | public function listContents(string $path, bool $deep): iterable
638 | {
639 | $bucketMgr = $this->getBucketManager();
640 |
641 | [$ret, $error] = $bucketMgr->listFiles($this->bucket, $path);
642 | $items = @$ret['items'];
643 | $marker = @$ret['marker'];
644 | $commonPrefixes = @$ret['commonPrefixes'];
645 | if ($error !== null) {
646 | $this->logQiniuError($error);
647 |
648 | return [];
649 | } else {
650 | $contents = [];
651 | foreach ($items as $item) {
652 | $normalized = [
653 | 'type' => 'file',
654 | 'path' => $item['key'],
655 | 'timestamp' => $item['putTime'],
656 | ];
657 |
658 | if ($normalized['type'] === 'file') {
659 | $normalized['size'] = $item['fsize'];
660 | }
661 |
662 | array_push($contents, $normalized);
663 | }
664 |
665 | return $contents;
666 | }
667 | }
668 |
669 | /**
670 | * Copy a file.
671 | *
672 | * @param string $source
673 | * @param string $destination
674 | * @param Config $config
675 | * @return void
676 | */
677 | public function copy(string $source, string $destination, Config $config): void
678 | {
679 | $bucketMgr = $this->getBucketManager();
680 |
681 | [$ret, $error] = $bucketMgr->copy($this->bucket, $source, $this->bucket, $destination);
682 | if ($error !== null) {
683 | $this->logQiniuError($error);
684 | throw UnableToCopyFile::fromLocationTo($source, $destination);
685 | }
686 | }
687 |
688 | /**
689 | * Delete a file.
690 | *
691 | * @param string $path
692 | *
693 | * @return bool
694 | */
695 | public function delete(string $path): void
696 | {
697 | $bucketMgr = $this->getBucketManager();
698 |
699 | [$ret, $error] = $bucketMgr->delete($this->bucket, $path);
700 | if ($error !== null) {
701 | $this->logQiniuError($error, $this->bucket . '/' . $path);
702 | throw UnableToDeleteFile::atLocation($path);
703 | }
704 | }
705 |
706 | public function fileExists(string $path): bool
707 | {
708 | $meta = $this->getMetadata($path);
709 | if ($meta) {
710 | return true;
711 | }
712 |
713 | return false;
714 | }
715 |
716 | public function directoryExists(string $path): bool
717 | {
718 | return $this->fileExists($path);
719 | }
720 |
721 | public function deleteDirectory(string $path): void
722 | {
723 | $this->delete($path);
724 | }
725 |
726 | public function createDirectory(string $path, Config $config): void
727 | {
728 | // Do not need to create directory. Just use write() to save your content.
729 | }
730 |
731 | public function setVisibility(string $path, string $visibility): void
732 | {
733 | throw UnableToSetVisibility::atLocation($path);
734 | }
735 |
736 | public function visibility(string $path): FileAttributes
737 | {
738 | throw UnableToSetVisibility::atLocation($path);
739 | }
740 |
741 | public function mimeType(string $path): FileAttributes
742 | {
743 | $stat = $this->getMetadata($path);
744 | if ($stat) {
745 | return new FileAttributes($path, null, null, null, $stat['mimeType']);
746 | }
747 | throw UnableToRetrieveMetadata::mimeType($path);
748 | }
749 |
750 | public function lastModified(string $path): FileAttributes
751 | {
752 | $stat = $this->getMetadata($path);
753 | if ($stat) {
754 | return new FileAttributes($path, null, null, $stat['putTime']);
755 | }
756 | throw UnableToRetrieveMetadata::mimeType($path);
757 | }
758 |
759 | public function fileSize(string $path): FileAttributes
760 | {
761 | $stat = $this->getMetadata($path);
762 | if ($stat) {
763 | return new FileAttributes($path, $stat['fsize']);
764 | }
765 | throw UnableToRetrieveMetadata::mimeType($path);
766 | }
767 |
768 | public function move(string $source, string $destination, Config $config): void
769 | {
770 | $bucketMgr = $this->getBucketManager();
771 | [$ret, $error] = $bucketMgr->move($this->bucket, $source, $this->bucket, $destination);
772 | if ($error !== null) {
773 | $this->logQiniuError($error);
774 | throw UnableToMoveFile::fromLocationTo($source, $destination);
775 | }
776 | }
777 |
778 | /**
779 | * @var string|null path prefix
780 | */
781 | protected $pathPrefix;
782 |
783 | /**
784 | * @var string
785 | */
786 | protected $pathSeparator = '/';
787 |
788 | /**
789 | * Set the path prefix.
790 | *
791 | * @param string $prefix
792 | *
793 | * @return void
794 | */
795 | public function setPathPrefix($prefix)
796 | {
797 | $prefix = (string)$prefix;
798 |
799 | if ($prefix === '') {
800 | $this->pathPrefix = null;
801 | return;
802 | }
803 |
804 | $this->pathPrefix = rtrim($prefix, '\\/') . $this->pathSeparator;
805 | }
806 |
807 | /**
808 | * Get the path prefix.
809 | *
810 | * @return string|null path prefix or null if pathPrefix is empty
811 | */
812 | public function getPathPrefix()
813 | {
814 | return $this->pathPrefix;
815 | }
816 |
817 | /**
818 | * Prefix a path.
819 | *
820 | * @param string $path
821 | *
822 | * @return string prefixed path
823 | */
824 | public function applyPathPrefix($path)
825 | {
826 | return $this->getPathPrefix() . ltrim($path, '\\/');
827 | }
828 |
829 | }
830 |
--------------------------------------------------------------------------------