├── Qiniu
├── Auth.php
├── Bucket.php
├── Client.php
├── Config.php
├── Http.php
├── Http
│ ├── Error.php
│ ├── Request.php
│ └── Response.php
└── PutExtra.php
├── README.md
└── index.php
/Qiniu/Auth.php:
--------------------------------------------------------------------------------
1 | accessKey = $accessKey;
12 | $this->secretKey = $secretKey;
13 | }
14 |
15 | public function Sign($data) // => $token
16 | {
17 | $sign = hash_hmac('sha1', $data, $this->secretKey, true);
18 | return $this->accessKey . ':' . $this->encode($sign);
19 | }
20 |
21 | public function SignWithData($data) // => $token
22 | {
23 | $data = $this->encode($data);
24 | return $this->sign($data) . ':' . $data;
25 | }
26 |
27 | public function SignRequest(\Qiniu\Http\Request $request) // => ($token, $error)
28 | {
29 | $url = $request->url;
30 | $url = parse_url($url['path']);
31 | $data = '';
32 | if (isset($url['path'])) {
33 | $data = $url['path'];
34 | }
35 | if (isset($url['query'])) {
36 | $data .= '?' . $url['query'];
37 | }
38 | $data .= "\n";
39 |
40 | if (isset($request->body) && $request->header['Content-Type'] === 'application/x-www-form-urlencoded') {
41 | $data .= $request->body;
42 | }
43 | return $this->sign($data);
44 | }
45 |
46 | public function encode($str) // URLSafeBase64Encode
47 | {
48 | $find = array('+', '/');
49 | $replace = array('-', '_');
50 | return str_replace($find, $replace, base64_encode($str));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Qiniu/Bucket.php:
--------------------------------------------------------------------------------
1 | scope = $params['scope'];
21 | if (isset($params['callbackUrl'])) {
22 | $this->callbackUrl = $params['callbackUrl'];
23 | }
24 | if (isset($params['callbackBody'])) {
25 | $this->callbackBody = $params['callbackBody'];
26 | }
27 | if (isset($params['returnUrl'])) {
28 | $this->returnUrl = $params['returnUrl'];
29 | }
30 | if (isset($params['returnBody'])) {
31 | $this->returnBody = $params['returnBody'];
32 | }
33 | if (isset($params['asyncOps'])) {
34 | $this->asyncOps = $params['asyncOps'];
35 | }
36 | if (isset($params['endUser'])) {
37 | $this->endUser = $params['endUser'];
38 | }
39 | if (isset($params['expires'])) {
40 | $this->expires = $params['expires'];
41 | }
42 | }
43 |
44 | /**
45 | * 根据初始化的参数获取预签名许可
46 | *
47 | * @return Json
48 | */
49 | public function policy()
50 | {
51 | $deadline = $this->expires;
52 | if ($deadline == 0) {
53 | $deadline = 3600;
54 | }
55 | $deadline += time();
56 |
57 | $policy = array('scope' => $this->scope, 'deadline' => $deadline);
58 | if (!empty($this->callbackUrl)) {
59 | $policy['callbackUrl'] = $this->callbackUrl;
60 | }
61 | if (!empty($this->callbackBody)) {
62 | $policy['callbackBody'] = $this->callbackBody;
63 | }
64 | if (!empty($this->returnUrl)) {
65 | $policy['returnUrl'] = $this->returnUrl;
66 | }
67 | if (!empty($this->returnBody)) {
68 | $policy['returnBody'] = $this->returnBody;
69 | }
70 | if (!empty($this->asyncOps)) {
71 | $policy['asyncOps'] = $this->asyncOps;
72 | }
73 | if (!empty($this->endUser)) {
74 | $policy['endUser'] = $this->endUser;
75 | }
76 | return json_encode($policy);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Qiniu/Client.php:
--------------------------------------------------------------------------------
1 |
6 | * @date 2013-08-25
7 | */
8 | namespace Qiniu;
9 |
10 | class Client
11 | {
12 | // Client 实例
13 | public static $client = array();
14 | // Client 名称
15 | public $name = null;
16 | // Client 设置类
17 | public $config = null;
18 | // Client 签名类
19 | public $auth = null;
20 | // Client 请求类
21 | public $http = null;
22 |
23 | /**
24 | * 实例化 Client
25 | *
26 | * @param $config,access_key和secret_key为必须,name为可选。
27 | *
28 | * @return void
29 | */
30 | public function __construct($config)
31 | {
32 | $this->config = new \Qiniu\Config();
33 | $this->auth = new \Qiniu\Auth($config['access_key'], $config['secret_key']);
34 | if (is_null(static::getInstance())) {
35 | if (isset($config['name'])) {
36 | $this->name = $config['name'];
37 | }
38 | is_null($this->name) ? static::$client['default'] = $this : static::$client[$this->name] = $this;
39 | }
40 | $this->http = new \Qiniu\Http();
41 | }
42 |
43 | /**
44 | * 通过静态方法获取 Client 实例
45 | *
46 | * @TODO 测试多帐号支持
47 | *
48 | * @param $name
49 | *
50 | * @return object
51 | */
52 | public static function getInstance($name = 'default')
53 | {
54 | if (empty(static::$client)) {
55 | return null;
56 | }
57 | return isset(static::$client[$name]) ? static::$client[$name] : static::$client['default'];
58 | }
59 |
60 | /**
61 | * PSR-0 autoloader
62 | */
63 | public static function autoload($className)
64 | {
65 | $thisClass = str_replace(__NAMESPACE__.'\\', '', __CLASS__);
66 |
67 | $baseDir = dirname(__DIR__);
68 |
69 | if (substr($baseDir, -strlen($thisClass)) === $thisClass) {
70 | $baseDir = substr($baseDir, 0, -strlen($thisClass));
71 | }
72 |
73 | $className = ltrim($className, '\\');
74 | $fileName = $baseDir;
75 | $namespace = '';
76 | if ($lastNsPos = strripos($className, '\\')) {
77 | $namespace = substr($className, 0, $lastNsPos);
78 | $className = substr($className, $lastNsPos + 1);
79 | $fileName .= DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
80 | }
81 | $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
82 |
83 | if (file_exists($fileName)) {
84 | require $fileName;
85 | }
86 | }
87 |
88 | /**
89 | * 注册 PSR-0 autoloader,如果你在使用 composer,请不要注册该函数。
90 | */
91 | public static function registerAutoloader()
92 | {
93 | spl_autoload_register(__NAMESPACE__ . "\\Client::autoload");
94 | }
95 |
96 | /**
97 | * 查看文件状态
98 | *
99 | * @param $bucket
100 | * @param $key
101 | *
102 | * @return array
103 | */
104 | public function rsStat($bucket, $key)
105 | {
106 | $uri = $this->config->rsURIStat($bucket, $key);
107 | return $this->http->call($this->getSignedRequest($uri));
108 | }
109 |
110 | /**
111 | * 复制文件
112 | *
113 | * @param $bucketSrc
114 | * @param $keySrc
115 | * @param $bucketDest
116 | * @param $keyDest
117 | *
118 | * @return array or null
119 | */
120 | public function rsCopy($bucketSrc, $keySrc, $bucketDest, $keyDest) // => $error
121 | {
122 | $uri = $this->config->rsURICopy($bucketSrc, $keySrc, $bucketDest, $keyDest);
123 | return $this->http->callNoRet($this->getSignedRequest($uri));
124 | }
125 |
126 | /**
127 | * 移动文件
128 | *
129 | * @param $bucketSrc
130 | * @param $keySrc
131 | * @param $bucketDest
132 | * @param $keyDest
133 | *
134 | * @return array or null
135 | */
136 | public function rsMove($bucketSrc, $keySrc, $bucketDest, $keyDest) // => $error
137 | {
138 | $uri = $this->config->rsURIMove($bucketSrc, $keySrc, $bucketDest, $keyDest);
139 | return $this->http->callNoRet($this->getSignedRequest($uri));
140 | }
141 |
142 | /**
143 | * 删除文件
144 | *
145 | * @param $bucket
146 | * @param $key
147 | *
148 | * @return array or null
149 | */
150 | public function rsDelete($bucket, $key) // => $error
151 | {
152 | $uri = $this->config->rsURIDelete($bucket, $key);
153 | return $this->http->callNoRet($this->getSignedRequest($uri));
154 | }
155 |
156 | /**
157 | * 通过 CURL 上传字符串文件
158 | *
159 | * @param $bucketName
160 | * @param $key
161 | * @param $body
162 | *
163 | * @return array
164 | */
165 | public function putString($bucketName, $key, $body)
166 | {
167 | $bucket = $this->getSignedBucket($bucketName);
168 | $request = $this->getStringRequest($bucket, $key, $body);
169 | return $this->http->call($request);
170 | }
171 |
172 | /**
173 | * 通过 CURL 上传本地文件
174 | *
175 | * @param $bucketName
176 | * @param $key
177 | * @param $file
178 | * @param $params,生成 upToken 的参数条件
179 | *
180 | * @return array
181 | */
182 | public function putFile($bucketName, $key, $body, $params = array())
183 | {
184 | $bucket = $this->getSignedBucket($bucketName, $params);
185 | $putExtra = new \Qiniu\PutExtra(array('crc32' => 1));
186 | $request = $this->getMultiRequest($bucket, $key, $body, $putExtra);
187 | return $this->http->call($request);
188 | }
189 |
190 | /**
191 | * 获取私有文件下载地址
192 | *
193 | * @param $domain
194 | * @param $key
195 | * @param $expires
196 | *
197 | * @return string
198 | */
199 | public function getPrivateUrl($domain, $key, $expires = 3600)
200 | {
201 | $baseUrl = $this->getDeadlineUrl($domain, $key, $expires);
202 | $token = $this->auth->sign($baseUrl);
203 | return $baseUrl . '&token=' . $token;
204 | }
205 |
206 | /**
207 | * 获取共有文件下载地址
208 | *
209 | * @param $domain
210 | * @param $key
211 | *
212 | * @return string
213 | */
214 | public function getPublicUrl($domain, $key)
215 | {
216 | $keyEsc = rawurlencode($key);
217 | return "http://$domain/$keyEsc";
218 | }
219 |
220 | /**
221 | * 获取已签名的 Request 类
222 | *
223 | * @param $uri
224 | *
225 | * @return object
226 | */
227 | public function getSignedRequest($uri)
228 | {
229 | $request = new \Qiniu\Http\Request(array('path' => $uri));
230 | $token = $this->auth->signRequest($request);
231 | $request->header['Authorization'] = "QBox $token";
232 | return $request;
233 | }
234 |
235 | /**
236 | * 获取已签名的 Bucket 类
237 | *
238 | * @param $bucketName
239 | * @param $params,生成 upToken 的参数条件
240 | *
241 | * @return object
242 | */
243 | public function getSignedBucket($bucketName, $params = array())
244 | {
245 | $scope = array('scope' => $bucketName);
246 | $policy = empty($params) ? $scope : (isset($params['scope']) ? $params : array_merge($scope, $params));
247 | $bucket = new \Qiniu\Bucket($policy);
248 | $bucket->token = $this->auth->signWithData($bucket->policy());
249 | return $bucket;
250 | }
251 |
252 | /**
253 | * 根据给定参数获取 upToken
254 | *
255 | * @param $params,scope为必要参数
256 | *
257 | * @return string
258 | */
259 | public function getUpToken($params)
260 | {
261 | $bucket = new \Qiniu\Bucket($params);
262 | return $this->auth->signWithData($bucket->policy());
263 | }
264 |
265 | /**
266 | * 获取上传字符串文件的 Request 类
267 | *
268 | * @param $bucket
269 | * @param $key
270 | * @param $params
271 | * @param $putExtra
272 | *
273 | * @return object
274 | */
275 | public function getStringRequest($bucket, $key, $params, $putExtra = null)
276 | {
277 | if ($putExtra === null) {
278 | $putExtra = new \Qiniu\PutExtra();
279 | }
280 | $data = $this->http->getStringData($bucket, $key, $params, $putExtra);
281 | list($contentType, $body) = $this->http->buildMultipartForm($data['fields'], $data['files']);
282 | $url = array('path' => \Qiniu\Config::QINIU_UP_HOST);
283 | if ($contentType === 'application/x-www-form-urlencoded') {
284 | if (is_array($body)) {
285 | $body = http_build_query($body);
286 | }
287 | }
288 | $request = new \Qiniu\Http\Request($url, $body);
289 | if ($contentType !== 'multipart/form-data') {
290 | $request->header['Content-Type'] = $contentType;
291 | }
292 | return $request;
293 | }
294 |
295 | /**
296 | * 获取上传本地文件的 Request 类
297 | *
298 | * @param $bucket
299 | * @param $key
300 | * @param $params
301 | * @param $putExtra
302 | *
303 | * @return object
304 | */
305 | public function getMultiRequest($bucket, $key, $params, $putExtra = null)
306 | {
307 | if ($putExtra === null) {
308 | $putExtra = new \Qiniu\PutExtra();
309 | }
310 | $body = is_array($params) && isset($params['file']) ? $params : array('file' => '@' . $params);
311 | $data = $this->http->getMultiData($bucket, $key, $body, $putExtra);
312 | $url = array('path' => \Qiniu\Config::QINIU_UP_HOST);
313 | $request = new \Qiniu\Http\Request($url, $data);
314 | $request->Header['Content-Type'] = 'multipart/form-data';
315 | return $request;
316 | }
317 |
318 | /**
319 | * 获取downloadToken
320 | *
321 | * @param $deadlineUrl
322 | *
323 | * @return string
324 | */
325 | public function getDownloadToken($deadlineUrl)
326 | {
327 | return $this->auth->sign($deadlineUrl);
328 | }
329 |
330 | /**
331 | * 为下载链接添加过期时间
332 | *
333 | * @param $domain
334 | * @param $key
335 | * @param $expires
336 | *
337 | * @return string
338 | */
339 | public function getDeadlineUrl($domain, $key, $expires = 3600)
340 | {
341 | $deadline = $expires + time();
342 | $baseUrl = $this->getPublicUrl($domain, $key);
343 | $pos = strpos($baseUrl, '?');
344 | if ($pos !== false) {
345 | $baseUrl .= '&e=';
346 | } else {
347 | $baseUrl .= '?e=';
348 | }
349 | return $baseUrl .= $deadline;
350 | }
351 | }
352 |
--------------------------------------------------------------------------------
/Qiniu/Config.php:
--------------------------------------------------------------------------------
1 | encode("$bucket:$key");
13 | }
14 |
15 | public function rsURIDelete($bucket, $key)
16 | {
17 | return static::QINIU_RS_HOST . '/delete/' . $this->encode("$bucket:$key");
18 | }
19 |
20 | public function rsURICopy($bucketSrc, $keySrc, $bucketDest, $keyDest)
21 | {
22 | return static::QINIU_RS_HOST
23 | . '/copy/' . $this->encode("$bucketSrc:$keySrc")
24 | . '/' . $this->encode("$bucketDest:$keyDest");
25 | }
26 |
27 | public function rsURIMove($bucketSrc, $keySrc, $bucketDest, $keyDest)
28 | {
29 | return static::QINIU_RS_HOST
30 | . '/move/' . $this->encode("$bucketSrc:$keySrc")
31 | . '/' . $this->encode("$bucketDest:$keyDest");
32 | }
33 |
34 | public function encode($str) // URLSafeBase64Encode
35 | {
36 | $find = array('+', '/');
37 | $replace = array('-', '_');
38 | return str_replace($find, $replace, base64_encode($str));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Qiniu/Http.php:
--------------------------------------------------------------------------------
1 | $error
25 | {
26 | $header = $response->header;
27 | $details = $this->headerGet($header, 'X-Log');
28 | $reqId = $this->headerGet($header, 'X-Reqid');
29 | $error = new \Qiniu\Http\Error($response->statusCode, null);
30 |
31 | if ($error->code > 299) {
32 | if ($response->contentLength !== 0) {
33 | if ($this->headerGet($header, 'Content-Type') === 'application/json') {
34 | $return = json_decode($response->body, true);
35 | $error->error = $return['error'];
36 | }
37 | }
38 | }
39 | return $error;
40 | }
41 |
42 | public function ret($response) // => ($data, $error)
43 | {
44 | $code = $response->statusCode;
45 | $data = null;
46 | if ($code >= 200 && $code <= 299) {
47 | if ($response->contentLength !== 0) {
48 | $data = json_decode($response->body, true);
49 | if ($data === null) {
50 | $error = new \Qiniu\Http\Error(0, json_last_error_msg());
51 | return array(null, $error);
52 | }
53 | }
54 | if ($code === 200) {
55 | return array($data, null);
56 | }
57 | }
58 | return array($data, $this->responseError($response));
59 | }
60 |
61 | public function call($request) // => ($data, $error)
62 | {
63 | list($response, $error) = $this->makeRequest($request);
64 | if ($error !== null) {
65 | return array(null, $error);
66 | }
67 | return $this->ret($response);
68 | }
69 |
70 | public function callNoRet($request) // => $error
71 | {
72 | list($response, $error) = $this->makeRequest($request);
73 | if ($error !== null) {
74 | return array(null, $error);
75 | }
76 | if ($response->statusCode === 200) {
77 | return null;
78 | }
79 | return $this->responseError($response);
80 | }
81 |
82 | public function incBody(\Qiniu\Http\Request $request) // => $incbody
83 | {
84 | $body = $request->body;
85 | if (!isset($body)) {
86 | return false;
87 | }
88 | $ct = $this->headerGet($request->header, 'Content-Type');
89 | if ($ct === 'application/x-www-form-urlencoded') {
90 | return true;
91 | }
92 | return false;
93 | }
94 |
95 | public function getStringData($bucket, $key, $body, $putExtra)
96 | {
97 | $fields = array('token' => $bucket->token);
98 | if ($key === null) {
99 | $fileName = '?';
100 | } else {
101 | $fileName = $key;
102 | $fields['key'] = $key;
103 | }
104 | if ($putExtra->checkCrc) {
105 | $fields['crc32'] = $putExtra->crc32;
106 | }
107 | $files = array(array('file', $fileName, $body));
108 | return array('fields' => $fields, 'files' => $files);
109 | }
110 |
111 | public function getMultiData($bucket, $key, $body, $putExtra)
112 | {
113 | $fields = array_merge($body, array('token' => $bucket->token));
114 | //$fields = array('token' => $bucket->token, 'file' => '@' . $localFile);
115 | if ($key === null) {
116 | $fname = '?';
117 | } else {
118 | $fname = $key;
119 | $fields['key'] = $key;
120 | }
121 | if ($putExtra->checkCrc) {
122 | if ($putExtra->checkCrc === 1) {
123 | $hash = hash_file('crc32b', $localFile);
124 | $array = unpack('N', pack('H*', $hash));
125 | $putExtra->crc32 = $array[1];
126 | }
127 | $fields['crc32'] = sprintf('%u', $putExtra->crc32);
128 | }
129 | return $fields;
130 | }
131 |
132 | public function makeRequest($req) // => ($resp, $error)
133 | {
134 | $ch = curl_init();
135 | $url = $req->url;
136 | $options = array(
137 | CURLOPT_RETURNTRANSFER => true,
138 | CURLOPT_SSL_VERIFYPEER => false,
139 | CURLOPT_SSL_VERIFYHOST => false,
140 | CURLOPT_CUSTOMREQUEST => 'POST',
141 | CURLOPT_URL => $url['path']
142 | );
143 | $httpHeader = $req->header;
144 | if (!empty($httpHeader))
145 | {
146 | $header = array();
147 | foreach($httpHeader as $key => $parsedUrlValue) {
148 | $header[] = "$key: $parsedUrlValue";
149 | }
150 | $options[CURLOPT_HTTPHEADER] = $header;
151 | }
152 | $body = $req->body;
153 | if (!empty($body)) {
154 | $options[CURLOPT_POSTFIELDS] = $body;
155 | }
156 | curl_setopt_array($ch, $options);
157 | $result = curl_exec($ch);
158 | $ret = curl_errno($ch);
159 | if ($ret !== 0) {
160 | $err = new \Qiniu\Http\Error(0, curl_error($ch));
161 | curl_close($ch);
162 | return array(null, $err);
163 | }
164 | $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
165 | $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
166 | curl_close($ch);
167 | $response = new \Qiniu\Http\Response($code, $result);
168 | $response->header['Content-Type'] = $contentType;
169 | return array($response, null);
170 | }
171 |
172 | public function buildMultipartForm($fields, $files) // => ($contentType, $body)
173 | {
174 | $data = array();
175 | $mimeBoundary = md5(microtime());
176 |
177 | foreach ($fields as $name => $val) {
178 | array_push($data, '--' . $mimeBoundary);
179 | array_push($data, "Content-Disposition: form-data; name=\"$name\"");
180 | array_push($data, '');
181 | array_push($data, $val);
182 | }
183 |
184 | foreach ($files as $file) {
185 | array_push($data, '--' . $mimeBoundary);
186 | list($name, $fileName, $fileBody) = $file;
187 | $fileName = $this->escapeQuotes($fileName);
188 | array_push($data, "Content-Disposition: form-data; name=\"$name\"; filename=\"$fileName\"");
189 | array_push($data, 'Content-Type: application/octet-stream');
190 | array_push($data, '');
191 | array_push($data, $fileBody);
192 | }
193 |
194 | array_push($data, '--' . $mimeBoundary . '--');
195 | array_push($data, '');
196 |
197 | $body = implode("\r\n", $data);
198 | $contentType = 'multipart/form-data; boundary=' . $mimeBoundary;
199 | return array($contentType, $body);
200 | }
201 |
202 | public function escapeQuotes($str)
203 | {
204 | $find = array("\\", "\"");
205 | $replace = array("\\\\", "\\\"");
206 | return str_replace($find, $replace, $str);
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/Qiniu/Http/Error.php:
--------------------------------------------------------------------------------
1 | code = $code;
14 | $this->error = $err;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Qiniu/Http/Request.php:
--------------------------------------------------------------------------------
1 | url = $url;
13 | $this->header = array();
14 | $this->body = $body;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Qiniu/Http/Response.php:
--------------------------------------------------------------------------------
1 | statusCode = $code;
14 | $this->header = array();
15 | $this->body = $body;
16 | $this->contentLength = strlen($body);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Qiniu/PutExtra.php:
--------------------------------------------------------------------------------
1 | params = $config['params'];
15 | }
16 | if (isset($config['mimeType'])) {
17 | $this->mimeType = $config['mimeType'];
18 | }
19 | if (isset($config['crc32'])) {
20 | $this->crc32 = $config['crc32'];
21 | }
22 | if (isset($config['checkCrc'])) {
23 | $this->checkCrc = $config['checkCrc'];
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 7NUP
2 |
3 | 单页面的基于七牛云存储的简单文件分享应用。
4 | 基于[RPUP](https://github.com/jysperm/RPUP)和[simple-qiniu-sdk](https://github.com/zither/simple-qiniu-sdk)构建。
5 |
6 | ## 特点
7 |
8 | * 七牛CDN全网加速
9 | * 支持多媒体在线处理,可按需[生成缩略图](http://developer.qiniu.com/docs/v6/api/reference/fop/image/imageview2.html)等
10 |
11 | ## 演示地址
12 |
13 | [http://7nup.sinaapp.com/](http://7nup.sinaapp.com/)
14 |
15 | ## 授权
16 |
17 | [GPLv3](https://github.com/jysperm/RPUP/blob/master/index.php#L8)
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | $QiniuAccessKey,'secret_key' => $QiniuSecretKey);
13 | $sdk = new \Qiniu\Client($config);
14 |
15 | ob_start();
16 |
17 | $htmlFileTableHead = <<< HTML
18 | 已上传文件列表
21 | HTML;
22 |
23 | $htmlFileTableFooter = <<< HTML
24 |
25 |