正在显示
8 个修改的文件
包含
739 行增加
和
0 行删除
addons/qiniu/Qiniu.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\qiniu; | ||
4 | + | ||
5 | +use addons\qiniu\library\Auth; | ||
6 | +use fast\Http; | ||
7 | +use think\Addons; | ||
8 | + | ||
9 | +/** | ||
10 | + * 七牛上传插件 | ||
11 | + */ | ||
12 | +class Qiniu extends Addons | ||
13 | +{ | ||
14 | + | ||
15 | + /** | ||
16 | + * 插件安装方法 | ||
17 | + * @return bool | ||
18 | + */ | ||
19 | + public function install() | ||
20 | + { | ||
21 | + return true; | ||
22 | + } | ||
23 | + | ||
24 | + /** | ||
25 | + * 插件卸载方法 | ||
26 | + * @return bool | ||
27 | + */ | ||
28 | + public function uninstall() | ||
29 | + { | ||
30 | + return true; | ||
31 | + } | ||
32 | + | ||
33 | + /** | ||
34 | + * 上传初始化时 | ||
35 | + */ | ||
36 | + public function uploadConfigInit(&$upload) | ||
37 | + { | ||
38 | + $config = $this->getConfig(); | ||
39 | + | ||
40 | + $policy = array( | ||
41 | + 'saveKey' => ltrim($config['savekey'], '/'), | ||
42 | + ); | ||
43 | + //如果启用服务端回调 | ||
44 | + if ($config['notifyenabled']) { | ||
45 | + $policy = array_merge($policy, [ | ||
46 | + 'callbackUrl' => $config['notifyurl'], | ||
47 | + 'callbackBody' => 'filename=$(fname)&key=$(key)&imageInfo=$(imageInfo)&filesize=$(fsize)&admin=$(x:admin)&user=$(x:user)' | ||
48 | + ]); | ||
49 | + } | ||
50 | + | ||
51 | + if ($config['uploadmode'] == 'client') { | ||
52 | + $auth = new Auth($config['app_key'], $config['secret_key']); | ||
53 | + $multipart['token'] = $auth->uploadToken($config['bucket'], null, $config['expire'], $policy); | ||
54 | + $multipart['x:admin'] = (int)session('admin.id'); | ||
55 | + $multipart['x:user'] = (int)cookie('uid'); | ||
56 | + $upload = [ | ||
57 | + 'cdnurl' => $config['cdnurl'], | ||
58 | + 'uploadurl' => $config['uploadurl'], | ||
59 | + 'bucket' => $config['bucket'], | ||
60 | + 'maxsize' => $config['maxsize'], | ||
61 | + 'mimetype' => $config['mimetype'], | ||
62 | + 'multipart' => $multipart, | ||
63 | + 'multiple' => $config['multiple'] ? true : false, | ||
64 | + ]; | ||
65 | + } else { | ||
66 | + $upload = array_merge($upload, [ | ||
67 | + 'cdnurl' => $config['cdnurl'], | ||
68 | + 'uploadurl' => addon_url('qiniu/index/upload'), | ||
69 | + 'maxsize' => $config['maxsize'], | ||
70 | + 'mimetype' => $config['mimetype'], | ||
71 | + 'multiple' => $config['multiple'] ? true : false, | ||
72 | + ]); | ||
73 | + } | ||
74 | + } | ||
75 | + | ||
76 | + /** | ||
77 | + * 附件删除后 | ||
78 | + */ | ||
79 | + public function uploadDelete($attachment) | ||
80 | + { | ||
81 | + $config = $this->getConfig(); | ||
82 | + if ($attachment['storage'] == 'qiniu' && isset($config['syncdelete']) && $config['syncdelete']) { | ||
83 | + $auth = new Auth($config['app_key'], $config['secret_key']); | ||
84 | + $entry = $config['bucket'] . ':' . ltrim($attachment->url, '/'); | ||
85 | + $encodedEntryURI = $auth->base64_urlSafeEncode($entry); | ||
86 | + $url = 'http://rs.qiniu.com/delete/' . $encodedEntryURI; | ||
87 | + $headers = $auth->authorization($url); | ||
88 | + //删除云储存文件 | ||
89 | + $ret = Http::sendRequest($url, [], 'POST', [CURLOPT_HTTPHEADER => ['Authorization: ' . $headers['Authorization']]]); | ||
90 | + //如果是服务端中转,还需要删除本地文件 | ||
91 | + if ($config['uploadmode'] == 'server') { | ||
92 | + $filePath = ROOT_PATH . 'public' . str_replace('/', DS, $attachment->url); | ||
93 | + if ($filePath) { | ||
94 | + @unlink($filePath); | ||
95 | + } | ||
96 | + } | ||
97 | + } | ||
98 | + return true; | ||
99 | + } | ||
100 | + | ||
101 | +} |
addons/qiniu/bootstrap.js
0 → 100644
1 | +//修改上传的接口调用 | ||
2 | +require(['upload'], function (Upload) { | ||
3 | + var _onUploadResponse = Upload.events.onUploadResponse; | ||
4 | + Upload.events.onUploadResponse = function (response) { | ||
5 | + try { | ||
6 | + var ret = typeof response === 'object' ? response : JSON.parse(response); | ||
7 | + if (ret.hasOwnProperty("code") && ret.hasOwnProperty("data")) { | ||
8 | + return _onUploadResponse.call(this, response); | ||
9 | + } else if (ret.hasOwnProperty("key") && !ret.hasOwnProperty("err_code")) { | ||
10 | + ret.code = 1; | ||
11 | + ret.data = { | ||
12 | + url: '/' + ret.key | ||
13 | + }; | ||
14 | + return _onUploadResponse.call(this, JSON.stringify(ret)); | ||
15 | + } | ||
16 | + } catch (e) { | ||
17 | + } | ||
18 | + return _onUploadResponse.call(this, response); | ||
19 | + | ||
20 | + }; | ||
21 | +}); |
addons/qiniu/config.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return array ( | ||
4 | + 0 => | ||
5 | + array ( | ||
6 | + 'name' => 'app_key', | ||
7 | + 'title' => 'app_key', | ||
8 | + 'type' => 'string', | ||
9 | + 'content' => | ||
10 | + array ( | ||
11 | + ), | ||
12 | + 'value' => 'your app_key', | ||
13 | + 'rule' => 'required', | ||
14 | + 'msg' => '', | ||
15 | + 'tip' => '请在个人中心 > 密钥管理中获取 > AK', | ||
16 | + 'ok' => '', | ||
17 | + 'extend' => '', | ||
18 | + ), | ||
19 | + 1 => | ||
20 | + array ( | ||
21 | + 'name' => 'secret_key', | ||
22 | + 'title' => 'secret_key', | ||
23 | + 'type' => 'string', | ||
24 | + 'content' => | ||
25 | + array ( | ||
26 | + ), | ||
27 | + 'value' => 'your secret_key', | ||
28 | + 'rule' => 'required', | ||
29 | + 'msg' => '', | ||
30 | + 'tip' => '请在个人中心 > 密钥管理中获取 > SK', | ||
31 | + 'ok' => '', | ||
32 | + 'extend' => '', | ||
33 | + ), | ||
34 | + 2 => | ||
35 | + array ( | ||
36 | + 'name' => 'bucket', | ||
37 | + 'title' => 'bucket', | ||
38 | + 'type' => 'string', | ||
39 | + 'content' => | ||
40 | + array ( | ||
41 | + ), | ||
42 | + 'value' => 'your bucket', | ||
43 | + 'rule' => 'required', | ||
44 | + 'msg' => '', | ||
45 | + 'tip' => '存储空间名称', | ||
46 | + 'ok' => '', | ||
47 | + 'extend' => '', | ||
48 | + ), | ||
49 | + 3 => | ||
50 | + array ( | ||
51 | + 'name' => 'uploadurl', | ||
52 | + 'title' => '上传接口地址', | ||
53 | + 'type' => 'select', | ||
54 | + 'content' => | ||
55 | + array ( | ||
56 | + 'https://upload-z0.qiniup.com' => '华东 https://upload-z0.qiniup.com', | ||
57 | + 'https://upload-z1.qiniup.com' => '华北 https://upload-z1.qiniup.com', | ||
58 | + 'https://upload-z2.qiniup.com' => '华南 https://upload-z2.qiniup.com', | ||
59 | + 'https://upload-na0.qiniup.com' => '北美 https://upload-na0.qiniup.com', | ||
60 | + 'https://upload-as0.qiniup.com' => '东南亚 https://upload-as0.qiniup.com', | ||
61 | + ), | ||
62 | + 'value' => 'https://upload-z2.qiniup.com', | ||
63 | + 'rule' => 'required', | ||
64 | + 'msg' => '', | ||
65 | + 'tip' => '推荐选择最近的地址', | ||
66 | + 'ok' => '', | ||
67 | + 'extend' => '', | ||
68 | + ), | ||
69 | + 4 => | ||
70 | + array ( | ||
71 | + 'name' => 'cdnurl', | ||
72 | + 'title' => 'CDN地址', | ||
73 | + 'type' => 'string', | ||
74 | + 'content' => | ||
75 | + array ( | ||
76 | + ), | ||
77 | + 'value' => 'http://yourbucket.bkt.clouddn.com', | ||
78 | + 'rule' => 'required', | ||
79 | + 'msg' => '', | ||
80 | + 'tip' => '未绑定CDN的话可使用七牛分配的测试域名', | ||
81 | + 'ok' => '', | ||
82 | + 'extend' => '', | ||
83 | + ), | ||
84 | + 5 => | ||
85 | + array ( | ||
86 | + 'name' => 'notifyenabled', | ||
87 | + 'title' => '启用服务端回调', | ||
88 | + 'type' => 'bool', | ||
89 | + 'content' => | ||
90 | + array ( | ||
91 | + ), | ||
92 | + 'value' => '0', | ||
93 | + 'rule' => '', | ||
94 | + 'msg' => '', | ||
95 | + 'tip' => '本地开发请禁用服务端回调', | ||
96 | + 'ok' => '', | ||
97 | + 'extend' => '', | ||
98 | + ), | ||
99 | + 6 => | ||
100 | + array ( | ||
101 | + 'name' => 'notifyurl', | ||
102 | + 'title' => '回调通知地址', | ||
103 | + 'type' => 'string', | ||
104 | + 'content' => | ||
105 | + array ( | ||
106 | + ), | ||
107 | + 'value' => 'http://www.yoursite.com/addons/qiniu/index/notify', | ||
108 | + 'rule' => '', | ||
109 | + 'msg' => '', | ||
110 | + 'tip' => '', | ||
111 | + 'ok' => '', | ||
112 | + 'extend' => '', | ||
113 | + ), | ||
114 | + 7 => | ||
115 | + array ( | ||
116 | + 'name' => 'uploadmode', | ||
117 | + 'title' => '上传模式', | ||
118 | + 'type' => 'select', | ||
119 | + 'content' => | ||
120 | + array ( | ||
121 | + 'client' => '客户端直传(速度快,无备份)', | ||
122 | + 'server' => '服务器中转(占用服务器带宽,有备份)', | ||
123 | + ), | ||
124 | + 'value' => 'server', | ||
125 | + 'rule' => '', | ||
126 | + 'msg' => '', | ||
127 | + 'tip' => '启用服务器中转时务必配置操作员和密码', | ||
128 | + 'ok' => '', | ||
129 | + 'extend' => '', | ||
130 | + ), | ||
131 | + 8 => | ||
132 | + array ( | ||
133 | + 'name' => 'savekey', | ||
134 | + 'title' => '保存文件名', | ||
135 | + 'type' => 'string', | ||
136 | + 'content' => | ||
137 | + array ( | ||
138 | + ), | ||
139 | + 'value' => '/uploads/$(year)$(mon)$(day)/$(etag)$(ext)', | ||
140 | + 'rule' => 'required', | ||
141 | + 'msg' => '', | ||
142 | + 'tip' => '', | ||
143 | + 'ok' => '', | ||
144 | + 'extend' => '', | ||
145 | + ), | ||
146 | + 9 => | ||
147 | + array ( | ||
148 | + 'name' => 'expire', | ||
149 | + 'title' => '上传有效时长', | ||
150 | + 'type' => 'string', | ||
151 | + 'content' => | ||
152 | + array ( | ||
153 | + ), | ||
154 | + 'value' => '600', | ||
155 | + 'rule' => 'required', | ||
156 | + 'msg' => '', | ||
157 | + 'tip' => '', | ||
158 | + 'ok' => '', | ||
159 | + 'extend' => '', | ||
160 | + ), | ||
161 | + 10 => | ||
162 | + array ( | ||
163 | + 'name' => 'maxsize', | ||
164 | + 'title' => '最大可上传', | ||
165 | + 'type' => 'string', | ||
166 | + 'content' => | ||
167 | + array ( | ||
168 | + ), | ||
169 | + 'value' => '10M', | ||
170 | + 'rule' => 'required', | ||
171 | + 'msg' => '', | ||
172 | + 'tip' => '', | ||
173 | + 'ok' => '', | ||
174 | + 'extend' => '', | ||
175 | + ), | ||
176 | + 11 => | ||
177 | + array ( | ||
178 | + 'name' => 'mimetype', | ||
179 | + 'title' => '可上传后缀格式', | ||
180 | + 'type' => 'string', | ||
181 | + 'content' => | ||
182 | + array ( | ||
183 | + ), | ||
184 | + 'value' => 'jpg,png,bmp,jpeg,gif,zip,rar,xls,xlsx', | ||
185 | + 'rule' => 'required', | ||
186 | + 'msg' => '', | ||
187 | + 'tip' => '', | ||
188 | + 'ok' => '', | ||
189 | + 'extend' => '', | ||
190 | + ), | ||
191 | + 12 => | ||
192 | + array ( | ||
193 | + 'name' => 'multiple', | ||
194 | + 'title' => '多文件上传', | ||
195 | + 'type' => 'bool', | ||
196 | + 'content' => | ||
197 | + array ( | ||
198 | + ), | ||
199 | + 'value' => '0', | ||
200 | + 'rule' => 'required', | ||
201 | + 'msg' => '', | ||
202 | + 'tip' => '', | ||
203 | + 'ok' => '', | ||
204 | + 'extend' => '', | ||
205 | + ), | ||
206 | + 13 => | ||
207 | + array ( | ||
208 | + 'name' => 'syncdelete', | ||
209 | + 'title' => '附件删除时是否同步删除文件', | ||
210 | + 'type' => 'bool', | ||
211 | + 'content' => | ||
212 | + array ( | ||
213 | + ), | ||
214 | + 'value' => '0', | ||
215 | + 'rule' => 'required', | ||
216 | + 'msg' => '', | ||
217 | + 'tip' => '', | ||
218 | + 'ok' => '', | ||
219 | + 'extend' => '', | ||
220 | + ), | ||
221 | + 14 => | ||
222 | + array ( | ||
223 | + 'name' => '__tips__', | ||
224 | + 'title' => '温馨提示', | ||
225 | + 'type' => '', | ||
226 | + 'content' => | ||
227 | + array ( | ||
228 | + ), | ||
229 | + 'value' => '在使用之前请注册七牛账号并进行认证,注册链接:<a href="https://portal.qiniu.com/signup?code=3l79xtos9w9qq" target="_blank">https://portal.qiniu.com/signup?code=3l79xtos9w9qq</a>', | ||
230 | + 'rule' => '', | ||
231 | + 'msg' => '', | ||
232 | + 'tip' => '', | ||
233 | + 'ok' => '', | ||
234 | + 'extend' => '', | ||
235 | + ), | ||
236 | +); |
addons/qiniu/controller/Index.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\qiniu\controller; | ||
4 | + | ||
5 | +use addons\qiniu\library\Auth; | ||
6 | +use app\common\model\Attachment; | ||
7 | +use think\addons\Controller; | ||
8 | +use think\Config; | ||
9 | + | ||
10 | +/** | ||
11 | + * 七牛管理 | ||
12 | + * | ||
13 | + */ | ||
14 | +class Index extends Controller | ||
15 | +{ | ||
16 | + public function index() | ||
17 | + { | ||
18 | + $this->error("当前插件暂无前台页面"); | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * 上传接口 | ||
23 | + */ | ||
24 | + public function upload() | ||
25 | + { | ||
26 | + Config::set('default_return_type', 'json'); | ||
27 | + if (!session('admin') && !$this->auth->id) { | ||
28 | + $this->error("请登录后再进行操作"); | ||
29 | + } | ||
30 | + $config = get_addon_config('qiniu'); | ||
31 | + | ||
32 | + $file = $this->request->file('file'); | ||
33 | + if (!$file || !$file->isValid()) { | ||
34 | + $this->error("请上传有效的文件"); | ||
35 | + } | ||
36 | + $fileInfo = $file->getInfo(); | ||
37 | + | ||
38 | + $filePath = $file->getRealPath() ?: $file->getPathname(); | ||
39 | + | ||
40 | + preg_match('/(\d+)(\w+)/', $config['maxsize'], $matches); | ||
41 | + $type = strtolower($matches[2]); | ||
42 | + $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3]; | ||
43 | + $size = (int)$config['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0); | ||
44 | + | ||
45 | + $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION)); | ||
46 | + $suffix = $suffix ? $suffix : 'file'; | ||
47 | + | ||
48 | + $md5 = md5_file($filePath); | ||
49 | + $search = ['$(year)', '$(mon)', '$(day)', '$(etag)', '$(ext)']; | ||
50 | + $replace = [date("Y"), date("m"), date("d"), $md5, '.' . $suffix]; | ||
51 | + $object = ltrim(str_replace($search, $replace, $config['savekey']), '/'); | ||
52 | + | ||
53 | + $mimetypeArr = explode(',', strtolower($config['mimetype'])); | ||
54 | + $typeArr = explode('/', $fileInfo['type']); | ||
55 | + | ||
56 | + //检查文件大小 | ||
57 | + if (!$file->checkSize($size)) { | ||
58 | + $this->error("起过最大可上传文件限制"); | ||
59 | + } | ||
60 | + | ||
61 | + //验证文件后缀 | ||
62 | + if ($config['mimetype'] !== '*' && | ||
63 | + ( | ||
64 | + !in_array($suffix, $mimetypeArr) | ||
65 | + || (stripos($typeArr[0] . '/', $config['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr))) | ||
66 | + ) | ||
67 | + ) { | ||
68 | + $this->error(__('上传格式限制')); | ||
69 | + } | ||
70 | + | ||
71 | + $savekey = '/' . $object; | ||
72 | + | ||
73 | + $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1); | ||
74 | + $fileName = substr($savekey, strripos($savekey, '/') + 1); | ||
75 | + //先上传到本地 | ||
76 | + $splInfo = $file->move(ROOT_PATH . '/public' . $uploadDir, $fileName); | ||
77 | + if ($splInfo) { | ||
78 | + $extparam = $this->request->post(); | ||
79 | + $filePath = $splInfo->getRealPath() ?: $splInfo->getPathname(); | ||
80 | + | ||
81 | + $sha1 = sha1_file($filePath); | ||
82 | + $imagewidth = $imageheight = 0; | ||
83 | + if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'])) { | ||
84 | + $imgInfo = getimagesize($splInfo->getPathname()); | ||
85 | + $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth; | ||
86 | + $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight; | ||
87 | + } | ||
88 | + $params = array( | ||
89 | + 'admin_id' => session('admin.id'), | ||
90 | + 'user_id' => $this->auth->id, | ||
91 | + 'filesize' => $fileInfo['size'], | ||
92 | + 'imagewidth' => $imagewidth, | ||
93 | + 'imageheight' => $imageheight, | ||
94 | + 'imagetype' => $suffix, | ||
95 | + 'imageframes' => 0, | ||
96 | + 'mimetype' => $fileInfo['type'], | ||
97 | + 'url' => $uploadDir . $splInfo->getSaveName(), | ||
98 | + 'uploadtime' => time(), | ||
99 | + 'storage' => 'local', | ||
100 | + 'sha1' => $sha1, | ||
101 | + 'extparam' => json_encode($extparam), | ||
102 | + ); | ||
103 | + $attachment = Attachment::create(array_filter($params), true); | ||
104 | + $policy = array( | ||
105 | + 'saveKey' => ltrim($savekey, '/'), | ||
106 | + ); | ||
107 | + $auth = new Auth($config['app_key'], $config['secret_key']); | ||
108 | + $token = $auth->uploadToken($config['bucket'], null, $config['expire'], $policy); | ||
109 | + $multipart = [ | ||
110 | + ['name' => 'token', 'contents' => $token], | ||
111 | + [ | ||
112 | + 'name' => 'file', | ||
113 | + 'contents' => fopen($filePath, 'r'), | ||
114 | + 'filename' => $fileName, | ||
115 | + ] | ||
116 | + ]; | ||
117 | + try { | ||
118 | + $client = new \GuzzleHttp\Client(); | ||
119 | + $res = $client->request('POST', $config['uploadurl'], [ | ||
120 | + 'multipart' => $multipart | ||
121 | + ]); | ||
122 | + $code = $res->getStatusCode(); | ||
123 | + //成功不做任何操作 | ||
124 | + } catch (\GuzzleHttp\Exception\ClientException $e) { | ||
125 | + $attachment->delete(); | ||
126 | + unlink($filePath); | ||
127 | + $this->error("上传失败"); | ||
128 | + } | ||
129 | + | ||
130 | + $url = '/' . $object; | ||
131 | + | ||
132 | + //上传成功后将存储变更为qiniu | ||
133 | + $attachment->storage = 'qiniu'; | ||
134 | + $attachment->save(); | ||
135 | + | ||
136 | + $this->success("上传成功", null, ['url' => $url]); | ||
137 | + } else { | ||
138 | + $this->error('上传失败'); | ||
139 | + } | ||
140 | + return; | ||
141 | + } | ||
142 | + | ||
143 | + /** | ||
144 | + * 通知回调 | ||
145 | + */ | ||
146 | + public function notify() | ||
147 | + { | ||
148 | + $config = get_addon_config('qiniu'); | ||
149 | + $auth = new Auth($config['app_key'], $config['secret_key']); | ||
150 | + $contentType = 'application/x-www-form-urlencoded'; | ||
151 | + $authorization = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : ''; | ||
152 | + if (!$authorization && function_exists('apache_request_headers')) { | ||
153 | + $headers = apache_request_headers(); | ||
154 | + $authorization = isset($headers['Authorization']) ? $headers['Authorization'] : ''; | ||
155 | + } | ||
156 | + | ||
157 | + $url = $config['notifyurl']; | ||
158 | + $body = file_get_contents('php://input'); | ||
159 | + $ret = $auth->verifyCallback($contentType, $authorization, $url, $body); | ||
160 | + if ($ret) { | ||
161 | + parse_str($body, $arr); | ||
162 | + $admin_id = isset($arr['admin']) ? $arr['admin'] : 0; | ||
163 | + $user_id = isset($arr['user']) ? $arr['user'] : 0; | ||
164 | + $imageInfo = json_decode($arr['imageInfo'], true); | ||
165 | + $params = array( | ||
166 | + 'admin_id' => (int)$admin_id, | ||
167 | + 'user_id' => (int)$user_id, | ||
168 | + 'filesize' => $arr['filesize'], | ||
169 | + 'imagewidth' => isset($imageInfo['width']) ? $imageInfo['width'] : 0, | ||
170 | + 'imageheight' => isset($imageInfo['height']) ? $imageInfo['height'] : 0, | ||
171 | + 'imagetype' => isset($imageInfo['format']) ? $imageInfo['format'] : '', | ||
172 | + 'imageframes' => 1, | ||
173 | + 'mimetype' => "image/" . (isset($imageInfo['format']) ? $imageInfo['format'] : ''), | ||
174 | + 'extparam' => '', | ||
175 | + 'url' => '/' . $arr['key'], | ||
176 | + 'uploadtime' => time(), | ||
177 | + 'storage' => 'qiniu' | ||
178 | + ); | ||
179 | + Attachment::create($params); | ||
180 | + return json(['ret' => 'success', 'code' => 1, 'data' => ['url' => $params['url']]]); | ||
181 | + } | ||
182 | + return json(['ret' => 'failed']); | ||
183 | + } | ||
184 | +} |
addons/qiniu/info.ini
0 → 100644
addons/qiniu/library/Auth.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\qiniu\library; | ||
4 | + | ||
5 | +final class Auth | ||
6 | +{ | ||
7 | + | ||
8 | + private $accessKey; | ||
9 | + private $secretKey; | ||
10 | + | ||
11 | + public function __construct($accessKey, $secretKey) | ||
12 | + { | ||
13 | + $this->accessKey = $accessKey; | ||
14 | + $this->secretKey = $secretKey; | ||
15 | + } | ||
16 | + | ||
17 | + public function getAccessKey() | ||
18 | + { | ||
19 | + return $this->accessKey; | ||
20 | + } | ||
21 | + | ||
22 | + public function sign($data) | ||
23 | + { | ||
24 | + $hmac = hash_hmac('sha1', $data, $this->secretKey, true); | ||
25 | + return $this->accessKey . ':' . $this->base64_urlSafeEncode($hmac); | ||
26 | + } | ||
27 | + | ||
28 | + public function signWithData($data) | ||
29 | + { | ||
30 | + $encodedData = $this->base64_urlSafeEncode($data); | ||
31 | + return $this->sign($encodedData) . ':' . $encodedData; | ||
32 | + } | ||
33 | + | ||
34 | + public function signRequest($urlString, $body, $contentType = null) | ||
35 | + { | ||
36 | + $url = parse_url($urlString); | ||
37 | + $data = ''; | ||
38 | + if (array_key_exists('path', $url)) { | ||
39 | + $data = $url['path']; | ||
40 | + } | ||
41 | + if (array_key_exists('query', $url)) { | ||
42 | + $data .= '?' . $url['query']; | ||
43 | + } | ||
44 | + $data .= "\n"; | ||
45 | + if ($body !== null && $contentType === 'application/x-www-form-urlencoded') { | ||
46 | + $data .= $body; | ||
47 | + } | ||
48 | + return $this->sign($data); | ||
49 | + } | ||
50 | + | ||
51 | + public function verifyCallback($contentType, $originAuthorization, $url, $body) | ||
52 | + { | ||
53 | + $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); | ||
54 | + return $originAuthorization === $authorization; | ||
55 | + } | ||
56 | + | ||
57 | + public function privateDownloadUrl($baseUrl, $expires = 3600) | ||
58 | + { | ||
59 | + $deadline = time() + $expires; | ||
60 | + $pos = strpos($baseUrl, '?'); | ||
61 | + if ($pos !== false) { | ||
62 | + $baseUrl .= '&e='; | ||
63 | + } else { | ||
64 | + $baseUrl .= '?e='; | ||
65 | + } | ||
66 | + $baseUrl .= $deadline; | ||
67 | + $token = $this->sign($baseUrl); | ||
68 | + return "$baseUrl&token=$token"; | ||
69 | + } | ||
70 | + | ||
71 | + public function uploadToken($bucket, $key = null, $expires = 3600, $policy = null, $strictPolicy = true) | ||
72 | + { | ||
73 | + $deadline = time() + $expires; | ||
74 | + $scope = $bucket; | ||
75 | + if ($key !== null) { | ||
76 | + $scope .= ':' . $key; | ||
77 | + } | ||
78 | + $args = self::copyPolicy($args, $policy, $strictPolicy); | ||
79 | + $args['scope'] = $scope; | ||
80 | + $args['deadline'] = $deadline; | ||
81 | + $b = json_encode($args); | ||
82 | + return $this->signWithData($b); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * 上传策略,参数规格详见 | ||
87 | + * http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html | ||
88 | + */ | ||
89 | + private static $policyFields = array( | ||
90 | + 'callbackUrl', | ||
91 | + 'callbackBody', | ||
92 | + 'callbackHost', | ||
93 | + 'callbackBodyType', | ||
94 | + 'callbackFetchKey', | ||
95 | + 'returnUrl', | ||
96 | + 'returnBody', | ||
97 | + 'endUser', | ||
98 | + 'saveKey', | ||
99 | + 'insertOnly', | ||
100 | + 'detectMime', | ||
101 | + 'mimeLimit', | ||
102 | + 'fsizeMin', | ||
103 | + 'fsizeLimit', | ||
104 | + 'persistentOps', | ||
105 | + 'persistentNotifyUrl', | ||
106 | + 'persistentPipeline', | ||
107 | + 'deleteAfterDays', | ||
108 | + 'fileType', | ||
109 | + 'upHosts', | ||
110 | + ); | ||
111 | + | ||
112 | + private static function copyPolicy(&$policy, $originPolicy, $strictPolicy) | ||
113 | + { | ||
114 | + if ($originPolicy === null) { | ||
115 | + return array(); | ||
116 | + } | ||
117 | + foreach ($originPolicy as $key => $value) { | ||
118 | + if (!$strictPolicy || in_array((string)$key, self::$policyFields, true)) { | ||
119 | + $policy[$key] = $value; | ||
120 | + } | ||
121 | + } | ||
122 | + return $policy; | ||
123 | + } | ||
124 | + | ||
125 | + public function authorization($url, $body = null, $contentType = null) | ||
126 | + { | ||
127 | + $authorization = 'QBox ' . $this->signRequest($url, $body, $contentType); | ||
128 | + return array('Authorization' => $authorization); | ||
129 | + } | ||
130 | + | ||
131 | + /** | ||
132 | + * 对提供的数据进行urlsafe的base64编码。 | ||
133 | + * | ||
134 | + * @param string $data 待编码的数据,一般为字符串 | ||
135 | + * | ||
136 | + * @return string 编码后的字符串 | ||
137 | + * @link http://developer.qiniu.com/docs/v6/api/overview/appendix.html#urlsafe-base64 | ||
138 | + */ | ||
139 | + function base64_urlSafeEncode($data) | ||
140 | + { | ||
141 | + $find = array('+', '/'); | ||
142 | + $replace = array('-', '_'); | ||
143 | + return str_replace($find, $replace, base64_encode($data)); | ||
144 | + } | ||
145 | + | ||
146 | + /** | ||
147 | + * 对提供的urlsafe的base64编码的数据进行解码 | ||
148 | + * | ||
149 | + * @param string $str 待解码的数据,一般为字符串 | ||
150 | + * | ||
151 | + * @return string 解码后的字符串 | ||
152 | + */ | ||
153 | + function base64_urlSafeDecode($str) | ||
154 | + { | ||
155 | + $find = array('-', '_'); | ||
156 | + $replace = array('+', '/'); | ||
157 | + return base64_decode(str_replace($find, $replace, $str)); | ||
158 | + } | ||
159 | + | ||
160 | +} |
@@ -4,6 +4,14 @@ return array ( | @@ -4,6 +4,14 @@ return array ( | ||
4 | 'autoload' => false, | 4 | 'autoload' => false, |
5 | 'hooks' => | 5 | 'hooks' => |
6 | array ( | 6 | array ( |
7 | + 'upload_config_init' => | ||
8 | + array ( | ||
9 | + 0 => 'qiniu', | ||
10 | + ), | ||
11 | + 'upload_delete' => | ||
12 | + array ( | ||
13 | + 0 => 'qiniu', | ||
14 | + ), | ||
7 | ), | 15 | ), |
8 | 'route' => | 16 | 'route' => |
9 | array ( | 17 | array ( |
@@ -12,6 +12,27 @@ define([], function () { | @@ -12,6 +12,27 @@ define([], function () { | ||
12 | } | 12 | } |
13 | }); | 13 | }); |
14 | 14 | ||
15 | +//修改上传的接口调用 | ||
16 | +require(['upload'], function (Upload) { | ||
17 | + var _onUploadResponse = Upload.events.onUploadResponse; | ||
18 | + Upload.events.onUploadResponse = function (response) { | ||
19 | + try { | ||
20 | + var ret = typeof response === 'object' ? response : JSON.parse(response); | ||
21 | + if (ret.hasOwnProperty("code") && ret.hasOwnProperty("data")) { | ||
22 | + return _onUploadResponse.call(this, response); | ||
23 | + } else if (ret.hasOwnProperty("key") && !ret.hasOwnProperty("err_code")) { | ||
24 | + ret.code = 1; | ||
25 | + ret.data = { | ||
26 | + url: '/' + ret.key | ||
27 | + }; | ||
28 | + return _onUploadResponse.call(this, JSON.stringify(ret)); | ||
29 | + } | ||
30 | + } catch (e) { | ||
31 | + } | ||
32 | + return _onUploadResponse.call(this, response); | ||
33 | + | ||
34 | + }; | ||
35 | +}); | ||
15 | require.config({ | 36 | require.config({ |
16 | paths: { | 37 | paths: { |
17 | 'summernote': '../addons/summernote/lang/summernote-zh-CN.min' | 38 | 'summernote': '../addons/summernote/lang/summernote-zh-CN.min' |
-
请 注册 或 登录 后发表评论