├── Plugin.php
├── README.md
└── sdk
├── auth_digest.php
├── conf.php
├── fop.php
├── http.php
├── io.php
├── resumable_io.php
├── rs.php
├── rs_utils.php
├── rsf.php
└── utils.php
/Plugin.php:
--------------------------------------------------------------------------------
1 | 源代码参考 & 注册七牛
4 | *
5 | * @package Qiniu File
6 | * @author abelyao
7 | * @version 1.2.0
8 | * @link http://www.abelyao.com/
9 | * @date 2014-02-22
10 | */
11 |
12 | class QiniuFile_Plugin implements Typecho_Plugin_Interface
13 | {
14 | // 激活插件
15 | public static function activate()
16 | {
17 | Typecho_Plugin::factory('Widget_Upload')->uploadHandle = array('QiniuFile_Plugin', 'uploadHandle');
18 | Typecho_Plugin::factory('Widget_Upload')->modifyHandle = array('QiniuFile_Plugin', 'modifyHandle');
19 | Typecho_Plugin::factory('Widget_Upload')->deleteHandle = array('QiniuFile_Plugin', 'deleteHandle');
20 | Typecho_Plugin::factory('Widget_Upload')->attachmentHandle = array('QiniuFile_Plugin', 'attachmentHandle');
21 | return _t('插件已经激活,需先配置七牛的信息!');
22 | }
23 |
24 |
25 | // 禁用插件
26 | public static function deactivate()
27 | {
28 | return _t('插件已被禁用');
29 | }
30 |
31 |
32 | // 插件配置面板
33 | public static function config(Typecho_Widget_Helper_Form $form)
34 | {
35 | $bucket = new Typecho_Widget_Helper_Form_Element_Text('bucket', null, null, _t('空间名称:'));
36 | $form->addInput($bucket->addRule('required', _t('“空间名称”不能为空!')));
37 |
38 | $accesskey = new Typecho_Widget_Helper_Form_Element_Text('accesskey', null, null, _t('AccessKey:'));
39 | $form->addInput($accesskey->addRule('required', _t('AccessKey 不能为空!')));
40 |
41 | $sercetkey = new Typecho_Widget_Helper_Form_Element_Text('sercetkey', null, null, _t('SecretKey:'));
42 | $form->addInput($sercetkey->addRule('required', _t('SecretKey 不能为空!')));
43 |
44 | $domain = new Typecho_Widget_Helper_Form_Element_Text('domain', null, 'http://', _t('绑定域名:'), _t('以 http:// 开头,结尾不要加 / !'));
45 | $form->addInput($domain->addRule('required', _t('请填写空间绑定的域名!'))->addRule('url', _t('您输入的域名格式错误!')));
46 |
47 | $savepath = new Typecho_Widget_Helper_Form_Element_Text('savepath', null, '{year}/{month}/', _t('保存路径格式:'), _t('附件保存路径的格式,默认为 Typecho 的 {year}/{month}/ 格式,注意前面不要加 / !
可选参数:{year} 年份、{month} 月份、{day} 日期'));
48 | $form->addInput($savepath->addRule('required', _t('请填写保存路径格式!')));
49 | }
50 |
51 |
52 | // 个人用户配置面板
53 | public static function personalConfig(Typecho_Widget_Helper_Form $form)
54 | {
55 | }
56 |
57 |
58 | // 获得插件配置信息
59 | public static function getConfig()
60 | {
61 | return Typecho_Widget::widget('Widget_Options')->plugin('QiniuFile');
62 | }
63 |
64 |
65 | // 初始化七牛SDK
66 | public static function initSDK($accesskey, $sercetkey)
67 | {
68 | // 调用 SDK 设置密钥
69 | require_once 'sdk/io.php';
70 | require_once 'sdk/rs.php';
71 | Qiniu_SetKeys($accesskey, $sercetkey);
72 | }
73 |
74 |
75 | // 删除文件
76 | public static function deleteFile($filepath)
77 | {
78 | // 获取插件配置
79 | $option = self::getConfig();
80 |
81 | // 初始化 SDK
82 | self::initSDK($option->accesskey, $option->sercetkey);
83 |
84 | // 删除
85 | $client = new Qiniu_MacHttpClient(null);
86 | return Qiniu_RS_Delete($client, $option->bucket, $filepath);
87 | }
88 |
89 |
90 | // 上传文件
91 | public static function uploadFile($file, $content = null)
92 | {
93 | // 获取上传文件
94 | if (empty($file['name'])) return false;
95 |
96 | // 校验扩展名
97 | $part = explode('.', $file['name']);
98 | $ext = (($length = count($part)) > 1) ? strtolower($part[$length-1]) : '';
99 | if (!Widget_Upload::checkFileType($ext)) return false;
100 |
101 | // 获取插件配置
102 | $option = self::getConfig();
103 | $date = new Typecho_Date(Typecho_Widget::widget('Widget_Options')->gmtTime);
104 |
105 | // 保存位置
106 | $savepath = preg_replace(array('/\{year\}/', '/\{month\}/', '/\{day\}/'), array($date->year, $date->month, $date->day), $option->savepath);
107 | $savename = $savepath . sprintf('%u', crc32(uniqid())) . '.' . $ext;
108 | if (isset($content))
109 | {
110 | $savename = $content['attachment']->path;
111 | self::deleteFile($savename);
112 | }
113 |
114 | // 上传文件
115 | $filename = $file['tmp_name'];
116 | if (!isset($filename)) return false;
117 |
118 | // 初始化 SDK
119 | self::initSDK($option->accesskey, $option->sercetkey);
120 |
121 | // 上传凭证
122 | $policy = new Qiniu_RS_PutPolicy($option->bucket);
123 | $token = $policy->Token(null);
124 | $extra = new Qiniu_PutExtra();
125 | $extra->Crc32 = 1;
126 |
127 | // 上传
128 | list($result, $error) = Qiniu_PutFile($token, $savename, $filename, $extra);
129 | if ($error == null)
130 | {
131 | return array
132 | (
133 | 'name' => $file['name'],
134 | 'path' => $savename,
135 | 'size' => $file['size'],
136 | 'type' => $ext,
137 | 'mime' => Typecho_Common::mimeContentType($savename)
138 | );
139 | }
140 | else return false;
141 | }
142 |
143 |
144 | // 上传文件处理函数
145 | public static function uploadHandle($file)
146 | {
147 | return self::uploadFile($file);
148 | }
149 |
150 |
151 | // 修改文件处理函数
152 | public static function modifyHandle($content, $file)
153 | {
154 | return self::uploadFile($file, $content);
155 | }
156 |
157 |
158 | // 删除文件
159 | public static function deleteHandle(array $content)
160 | {
161 | self::deleteFile($content['attachment']->path);
162 | }
163 |
164 |
165 | // 获取实际文件绝对访问路径
166 | public static function attachmentHandle(array $content)
167 | {
168 | $option = self::getConfig();
169 | return Typecho_Common::url($content['attachment']->path, $option->domain);
170 | }
171 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Typecho-QiniuFile
2 | ---
3 |
4 | Qiniu File 是一款 Typecho 的七牛云存储插件,可将 Typecho 的文件功能接入到七牛云存储中,包括上传附件、修改附件、删除附件,以及获取文件在七牛的绝对网址。文件目录结构默认与 Typecho 的 `/year/month/` 保持一致,也可自定义配置,方便迁移。
5 |
6 | #### 使用方法:
7 | 第一步:下载本插件,放在 `usr/plugins/` 目录中;
8 | 第二步:激活插件;
9 | 第三步:填写空间名称、Access Key、Secret Key、域名 等配置;
10 | 第四步:完成。
11 |
12 | #### 特别说明:
13 | 这个插件是为满足个人需求而编写,兼容性方面多多少少会有不完善的地方,如有需求,可根据源代码自行修改,或者与我联系。
14 |
15 | #### 与我联系:
16 | 作者:abelyao
17 | 主页:[www.abelyao.com](http://www.abelyao.com/)
18 | 或者通过 Typecho 官方QQ群 `8110782` 找到我
19 |
--------------------------------------------------------------------------------
/sdk/auth_digest.php:
--------------------------------------------------------------------------------
1 | AccessKey = $accessKey;
16 | $this->SecretKey = $secretKey;
17 | }
18 |
19 | public function Sign($data) // => $token
20 | {
21 | $sign = hash_hmac('sha1', $data, $this->SecretKey, true);
22 | return $this->AccessKey . ':' . Qiniu_Encode($sign);
23 | }
24 |
25 | public function SignWithData($data) // => $token
26 | {
27 | $data = Qiniu_Encode($data);
28 | return $this->Sign($data) . ':' . $data;
29 | }
30 |
31 | public function SignRequest($req, $incbody) // => ($token, $error)
32 | {
33 | $url = $req->URL;
34 | $url = parse_url($url['path']);
35 | $data = '';
36 | if (isset($url['path'])) {
37 | $data = $url['path'];
38 | }
39 | if (isset($url['query'])) {
40 | $data .= '?' . $url['query'];
41 | }
42 | $data .= "\n";
43 |
44 | if ($incbody) {
45 | $data .= $req->Body;
46 | }
47 | return $this->Sign($data);
48 | }
49 | }
50 |
51 | function Qiniu_SetKeys($accessKey, $secretKey)
52 | {
53 | global $QINIU_ACCESS_KEY;
54 | global $QINIU_SECRET_KEY;
55 |
56 | $QINIU_ACCESS_KEY = $accessKey;
57 | $QINIU_SECRET_KEY = $secretKey;
58 | }
59 |
60 | function Qiniu_RequireMac($mac) // => $mac
61 | {
62 | if (isset($mac)) {
63 | return $mac;
64 | }
65 |
66 | global $QINIU_ACCESS_KEY;
67 | global $QINIU_SECRET_KEY;
68 |
69 | return new Qiniu_Mac($QINIU_ACCESS_KEY, $QINIU_SECRET_KEY);
70 | }
71 |
72 | function Qiniu_Sign($mac, $data) // => $token
73 | {
74 | return Qiniu_RequireMac($mac)->Sign($data);
75 | }
76 |
77 | function Qiniu_SignWithData($mac, $data) // => $token
78 | {
79 | return Qiniu_RequireMac($mac)->SignWithData($data);
80 | }
81 |
82 | // ----------------------------------------------------------
83 |
84 |
--------------------------------------------------------------------------------
/sdk/conf.php:
--------------------------------------------------------------------------------
1 | ';
15 | $QINIU_SECRET_KEY = '';
16 |
17 |
--------------------------------------------------------------------------------
/sdk/fop.php:
--------------------------------------------------------------------------------
1 | Mode);
18 |
19 | if (!empty($this->Width)) {
20 | $ops[] = 'w/' . $this->Width;
21 | }
22 | if (!empty($this->Height)) {
23 | $ops[] = 'h/' . $this->Height;
24 | }
25 | if (!empty($this->Quality)) {
26 | $ops[] = 'q/' . $this->Quality;
27 | }
28 | if (!empty($this->Format)) {
29 | $ops[] = 'format/' . $this->Format;
30 | }
31 |
32 | return $url . "?imageView/" . implode('/', $ops);
33 | }
34 | }
35 |
36 | // --------------------------------------------------------------------------------
37 | // class Qiniu_Exif
38 |
39 | class Qiniu_Exif {
40 |
41 | public function MakeRequest($url)
42 | {
43 | return $url . "?exif";
44 | }
45 |
46 | }
47 |
48 | // --------------------------------------------------------------------------------
49 | // class Qiniu_ImageInfo
50 |
51 | class Qiniu_ImageInfo {
52 |
53 | public function MakeRequest($url)
54 | {
55 | return $url . "?imageInfo";
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/sdk/http.php:
--------------------------------------------------------------------------------
1 | Code = $code;
18 | $this->Err = $err;
19 | }
20 | }
21 |
22 | // --------------------------------------------------------------------------------
23 | // class Qiniu_Request
24 |
25 | class Qiniu_Request
26 | {
27 | public $URL;
28 | public $Header;
29 | public $Body;
30 |
31 | public function __construct($url, $body)
32 | {
33 | $this->URL = $url;
34 | $this->Header = array();
35 | $this->Body = $body;
36 | }
37 | }
38 |
39 | // --------------------------------------------------------------------------------
40 | // class Qiniu_Response
41 |
42 | class Qiniu_Response
43 | {
44 | public $StatusCode;
45 | public $Header;
46 | public $ContentLength;
47 | public $Body;
48 |
49 | public function __construct($code, $body)
50 | {
51 | $this->StatusCode = $code;
52 | $this->Header = array();
53 | $this->Body = $body;
54 | $this->ContentLength = strlen($body);
55 | }
56 | }
57 |
58 | // --------------------------------------------------------------------------------
59 | // class Qiniu_Header
60 |
61 | function Qiniu_Header_Get($header, $key) // => $val
62 | {
63 | $val = @$header[$key];
64 | if (isset($val)) {
65 | if (is_array($val)) {
66 | return $val[0];
67 | }
68 | return $val;
69 | } else {
70 | return '';
71 | }
72 | }
73 |
74 | function Qiniu_ResponseError($resp) // => $error
75 | {
76 | $header = $resp->Header;
77 | $details = Qiniu_Header_Get($header, 'X-Log');
78 | $reqId = Qiniu_Header_Get($header, 'X-Reqid');
79 | $err = new Qiniu_Error($resp->StatusCode, null);
80 |
81 | if ($err->Code > 299) {
82 | if ($resp->ContentLength !== 0) {
83 | if (Qiniu_Header_Get($header, 'Content-Type') === 'application/json') {
84 | $ret = json_decode($resp->Body, true);
85 | $err->Err = $ret['error'];
86 | }
87 | }
88 | }
89 | return $err;
90 | }
91 |
92 | // --------------------------------------------------------------------------------
93 | // class Qiniu_Client
94 |
95 | function Qiniu_Client_incBody($req) // => $incbody
96 | {
97 | $body = $req->Body;
98 | if (!isset($body)) {
99 | return false;
100 | }
101 |
102 | $ct = Qiniu_Header_Get($req->Header, 'Content-Type');
103 | if ($ct === 'application/x-www-form-urlencoded') {
104 | return true;
105 | }
106 | return false;
107 | }
108 |
109 | function Qiniu_Client_do($req) // => ($resp, $error)
110 | {
111 | $ch = curl_init();
112 | $url = $req->URL;
113 | $options = array(
114 | CURLOPT_RETURNTRANSFER => true,
115 | CURLOPT_SSL_VERIFYPEER => false,
116 | CURLOPT_SSL_VERIFYHOST => false,
117 | CURLOPT_CUSTOMREQUEST => 'POST',
118 | CURLOPT_URL => $url['path']
119 | );
120 | $httpHeader = $req->Header;
121 | if (!empty($httpHeader))
122 | {
123 | $header = array();
124 | foreach($httpHeader as $key => $parsedUrlValue) {
125 | $header[] = "$key: $parsedUrlValue";
126 | }
127 | $options[CURLOPT_HTTPHEADER] = $header;
128 | }
129 | $body = $req->Body;
130 | if (!empty($body)) {
131 | $options[CURLOPT_POSTFIELDS] = $body;
132 | }
133 | curl_setopt_array($ch, $options);
134 | $result = curl_exec($ch);
135 | $ret = curl_errno($ch);
136 | if ($ret !== 0) {
137 | $err = new Qiniu_Error(0, curl_error($ch));
138 | curl_close($ch);
139 | return array(null, $err);
140 | }
141 | $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
142 | $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
143 | curl_close($ch);
144 | $resp = new Qiniu_Response($code, $result);
145 | $resp->Header['Content-Type'] = $contentType;
146 | return array($resp, null);
147 | }
148 |
149 | class Qiniu_HttpClient
150 | {
151 | public function RoundTrip($req) // => ($resp, $error)
152 | {
153 | return Qiniu_Client_do($req);
154 | }
155 | }
156 |
157 | class Qiniu_MacHttpClient
158 | {
159 | public $Mac;
160 |
161 | public function __construct($mac)
162 | {
163 | $this->Mac = Qiniu_RequireMac($mac);
164 | }
165 |
166 | public function RoundTrip($req) // => ($resp, $error)
167 | {
168 | $incbody = Qiniu_Client_incBody($req);
169 | $token = $this->Mac->SignRequest($req, $incbody);
170 | $req->Header['Authorization'] = "QBox $token";
171 | return Qiniu_Client_do($req);
172 | }
173 | }
174 |
175 | // --------------------------------------------------------------------------------
176 |
177 | function Qiniu_Client_ret($resp) // => ($data, $error)
178 | {
179 | $code = $resp->StatusCode;
180 | $data = null;
181 | if ($code >= 200 && $code <= 299) {
182 | if ($resp->ContentLength !== 0) {
183 | $data = json_decode($resp->Body, true);
184 | if ($data === null) {
185 | $err_msg = function_exists('json_last_error_msg') ? json_last_error_msg() : "error with content:" . $resp->Body;
186 | $err = new Qiniu_Error(0, $err_msg);
187 | return array(null, $err);
188 | }
189 | }
190 | if ($code === 200) {
191 | return array($data, null);
192 | }
193 | }
194 | return array($data, Qiniu_ResponseError($resp));
195 | }
196 |
197 | function Qiniu_Client_Call($self, $url) // => ($data, $error)
198 | {
199 | $u = array('path' => $url);
200 | $req = new Qiniu_Request($u, null);
201 | list($resp, $err) = $self->RoundTrip($req);
202 | if ($err !== null) {
203 | return array(null, $err);
204 | }
205 | return Qiniu_Client_ret($resp);
206 | }
207 |
208 | function Qiniu_Client_CallNoRet($self, $url) // => $error
209 | {
210 | $u = array('path' => $url);
211 | $req = new Qiniu_Request($u, null);
212 | list($resp, $err) = $self->RoundTrip($req);
213 | if ($err !== null) {
214 | return array(null, $err);
215 | }
216 | if ($resp->StatusCode === 200) {
217 | return null;
218 | }
219 | return Qiniu_ResponseError($resp);
220 | }
221 |
222 | function Qiniu_Client_CallWithForm(
223 | $self, $url, $params, $contentType = 'application/x-www-form-urlencoded') // => ($data, $error)
224 | {
225 | $u = array('path' => $url);
226 | if ($contentType === 'application/x-www-form-urlencoded') {
227 | if (is_array($params)) {
228 | $params = http_build_query($params);
229 | }
230 | }
231 | $req = new Qiniu_Request($u, $params);
232 | if ($contentType !== 'multipart/form-data') {
233 | $req->Header['Content-Type'] = $contentType;
234 | }
235 | list($resp, $err) = $self->RoundTrip($req);
236 | if ($err !== null) {
237 | return array(null, $err);
238 | }
239 | return Qiniu_Client_ret($resp);
240 | }
241 |
242 | // --------------------------------------------------------------------------------
243 |
244 | function Qiniu_Client_CallWithMultipartForm($self, $url, $fields, $files)
245 | {
246 | list($contentType, $body) = Qiniu_Build_MultipartForm($fields, $files);
247 | return Qiniu_Client_CallWithForm($self, $url, $body, $contentType);
248 | }
249 |
250 | function Qiniu_Build_MultipartForm($fields, $files) // => ($contentType, $body)
251 | {
252 | $data = array();
253 | $mimeBoundary = md5(microtime());
254 |
255 | foreach ($fields as $name => $val) {
256 | array_push($data, '--' . $mimeBoundary);
257 | array_push($data, "Content-Disposition: form-data; name=\"$name\"");
258 | array_push($data, '');
259 | array_push($data, $val);
260 | }
261 |
262 | foreach ($files as $file) {
263 | array_push($data, '--' . $mimeBoundary);
264 | list($name, $fileName, $fileBody, $mimeType) = $file;
265 | $mimeType = empty($mimeType) ? 'application/octet-stream' : $mimeType;
266 | $fileName = Qiniu_escapeQuotes($fileName);
267 | array_push($data, "Content-Disposition: form-data; name=\"$name\"; filename=\"$fileName\"");
268 | array_push($data, "Content-Type: $mimeType");
269 | array_push($data, '');
270 | array_push($data, $fileBody);
271 | }
272 |
273 | array_push($data, '--' . $mimeBoundary . '--');
274 | array_push($data, '');
275 |
276 | $body = implode("\r\n", $data);
277 | $contentType = 'multipart/form-data; boundary=' . $mimeBoundary;
278 | return array($contentType, $body);
279 | }
280 |
281 | function Qiniu_escapeQuotes($str)
282 | {
283 | $find = array("\\", "\"");
284 | $replace = array("\\\\", "\\\"");
285 | return str_replace($find, $replace, $str);
286 | }
287 |
288 | // --------------------------------------------------------------------------------
289 |
290 |
--------------------------------------------------------------------------------
/sdk/io.php:
--------------------------------------------------------------------------------
1 | ($putRet, $err)
18 | {
19 | global $QINIU_UP_HOST;
20 |
21 | if ($putExtra === null) {
22 | $putExtra = new Qiniu_PutExtra;
23 | }
24 |
25 | $fields = array('token' => $upToken);
26 | if ($key === null) {
27 | $fname = '?';
28 | } else {
29 | $fname = $key;
30 | $fields['key'] = $key;
31 | }
32 | if ($putExtra->CheckCrc) {
33 | $fields['crc32'] = $putExtra->Crc32;
34 | }
35 |
36 | $files = array(array('file', $fname, $body, $putExtra->MimeType));
37 |
38 | $client = new Qiniu_HttpClient;
39 | return Qiniu_Client_CallWithMultipartForm($client, $QINIU_UP_HOST, $fields, $files);
40 | }
41 |
42 | function Qiniu_PutFile($upToken, $key, $localFile, $putExtra) // => ($putRet, $err)
43 | {
44 | global $QINIU_UP_HOST;
45 |
46 | if ($putExtra === null) {
47 | $putExtra = new Qiniu_PutExtra;
48 | }
49 |
50 | if (!empty($putExtra->MimeType)) {
51 | $localFile .= ';type=' . $putExtra->MimeType;
52 | }
53 |
54 | $fields = array('token' => $upToken, 'file' => '@' . $localFile);
55 | if ($key === null) {
56 | $fname = '?';
57 | } else {
58 | $fname = $key;
59 | $fields['key'] = $key;
60 | }
61 | if ($putExtra->CheckCrc) {
62 | if ($putExtra->CheckCrc === 1) {
63 | $hash = hash_file('crc32b', $localFile);
64 | $array = unpack('N', pack('H*', $hash));
65 | $putExtra->Crc32 = $array[1];
66 | }
67 | $fields['crc32'] = sprintf('%u', $putExtra->Crc32);
68 | }
69 |
70 | $client = new Qiniu_HttpClient;
71 | return Qiniu_Client_CallWithForm($client, $QINIU_UP_HOST, $fields, 'multipart/form-data');
72 | }
73 |
74 | // ----------------------------------------------------------
75 |
76 |
--------------------------------------------------------------------------------
/sdk/resumable_io.php:
--------------------------------------------------------------------------------
1 | Bucket = $bucket;
22 | }
23 | }
24 |
25 | // ----------------------------------------------------------
26 | // func Qiniu_Rio_BlockCount
27 |
28 | define('QINIU_RIO_BLOCK_BITS', 22);
29 | define('QINIU_RIO_BLOCK_SIZE', 1 << QINIU_RIO_BLOCK_BITS); // 4M
30 |
31 | function Qiniu_Rio_BlockCount($fsize) // => $blockCnt
32 | {
33 | return ($fsize + (QINIU_RIO_BLOCK_SIZE - 1)) >> QINIU_RIO_BLOCK_BITS;
34 | }
35 |
36 | // ----------------------------------------------------------
37 | // internal func Qiniu_Rio_Mkblock/Mkfile
38 |
39 | function Qiniu_Rio_Mkblock($self, $host, $reader, $size) // => ($blkputRet, $err)
40 | {
41 | if (is_resource($reader)) {
42 | $body = fread($reader, $size);
43 | if ($body === false) {
44 | $err = Qiniu_NewError(0, 'fread failed');
45 | return array(null, $err);
46 | }
47 | } else {
48 | list($body, $err) = $reader->Read($size);
49 | if ($err !== null) {
50 | return array(null, $err);
51 | }
52 | }
53 | if (strlen($body) != $size) {
54 | $err = Qiniu_NewError(0, 'fread failed: unexpected eof');
55 | return array(null, $err);
56 | }
57 |
58 | $url = $host . '/mkblk/' . $size;
59 | return Qiniu_Client_CallWithForm($self, $url, $body, 'application/octet-stream');
60 | }
61 |
62 |
63 | function Qiniu_Rio_Mkfile($self, $host, $key, $fsize, $extra) // => ($putRet, $err)
64 | {
65 | $url = $host . '/mkfile/' . $fsize;
66 | if ($key !== null) {
67 | $url .= '/key/' . Qiniu_Encode($key);
68 | }
69 | if (!empty($extra->MimeType)) {
70 | $url .= '/mimeType/' . Qiniu_Encode($extra->MimeType);
71 | }
72 |
73 | $ctxs = array();
74 | foreach ($extra->Progresses as $prog) {
75 | $ctxs []= $prog['ctx'];
76 | }
77 | $body = implode(',', $ctxs);
78 |
79 | return Qiniu_Client_CallWithForm($self, $url, $body, 'application/octet-stream');
80 | }
81 |
82 | // ----------------------------------------------------------
83 | // class Qiniu_Rio_UploadClient
84 |
85 | class Qiniu_Rio_UploadClient
86 | {
87 | public $uptoken;
88 |
89 | public function __construct($uptoken)
90 | {
91 | $this->uptoken = $uptoken;
92 | }
93 |
94 | public function RoundTrip($req) // => ($resp, $error)
95 | {
96 | $token = $this->uptoken;
97 | $req->Header['Authorization'] = "UpToken $token";
98 | return Qiniu_Client_do($req);
99 | }
100 | }
101 |
102 | // ----------------------------------------------------------
103 | // class Qiniu_Rio_Put/PutFile
104 |
105 | function Qiniu_Rio_Put($upToken, $key, $body, $fsize, $putExtra) // => ($putRet, $err)
106 | {
107 | global $QINIU_UP_HOST;
108 |
109 | $self = new Qiniu_Rio_UploadClient($upToken);
110 |
111 | $progresses = array();
112 | $uploaded = 0;
113 | while ($uploaded < $fsize) {
114 | if ($fsize < $uploaded + QINIU_RIO_BLOCK_SIZE) {
115 | $bsize = $fsize - $uploaded;
116 | } else {
117 | $bsize = QINIU_RIO_BLOCK_SIZE;
118 | }
119 | list($blkputRet, $err) = Qiniu_Rio_Mkblock($self, $QINIU_UP_HOST, $body, $bsize);
120 | $host = $blkputRet['host'];
121 | $uploaded += $bsize;
122 | $progresses []= $blkputRet;
123 | }
124 |
125 | $putExtra->Progresses = $progresses;
126 | return Qiniu_Rio_Mkfile($self, $QINIU_UP_HOST, $key, $fsize, $putExtra);
127 | }
128 |
129 | function Qiniu_Rio_PutFile($upToken, $key, $localFile, $putExtra) // => ($putRet, $err)
130 | {
131 | $fp = fopen($localFile, 'rb');
132 | if ($fp === false) {
133 | $err = Qiniu_NewError(0, 'fopen failed');
134 | return array(null, $err);
135 | }
136 |
137 | $fi = fstat($fp);
138 | $result = Qiniu_Rio_Put($upToken, $key, $fp, $fi['size'], $putExtra);
139 | fclose($fp);
140 | return $result;
141 | }
142 |
143 | // ----------------------------------------------------------
144 |
145 |
--------------------------------------------------------------------------------
/sdk/rs.php:
--------------------------------------------------------------------------------
1 | $privateUrl
13 | {
14 | $deadline = $this->Expires;
15 | if ($deadline == 0) {
16 | $deadline = 3600;
17 | }
18 | $deadline += time();
19 |
20 | $pos = strpos($baseUrl, '?');
21 | if ($pos !== false) {
22 | $baseUrl .= '&e=';
23 | } else {
24 | $baseUrl .= '?e=';
25 | }
26 | $baseUrl .= $deadline;
27 |
28 | $token = Qiniu_Sign($mac, $baseUrl);
29 | return "$baseUrl&token=$token";
30 | }
31 | }
32 |
33 | function Qiniu_RS_MakeBaseUrl($domain, $key) // => $baseUrl
34 | {
35 | $keyEsc = rawurlencode($key);
36 | return "http://$domain/$keyEsc";
37 | }
38 |
39 | // --------------------------------------------------------------------------------
40 | // class Qiniu_RS_PutPolicy
41 |
42 | class Qiniu_RS_PutPolicy
43 | {
44 | public $Scope; //必填
45 | public $Expires; //默认为3600s
46 | public $CallbackUrl;
47 | public $CallbackBody;
48 | public $ReturnUrl;
49 | public $ReturnBody;
50 | public $AsyncOps;
51 | public $EndUser;
52 | public $InsertOnly; //若非0,则任何情况下无法覆盖上传
53 | public $DetectMime; //若非0,则服务端根据内容自动确定MimeType
54 | public $FsizeLimit;
55 | public $SaveKey;
56 | public $PersistentOps;
57 | public $PersistentNotifyUrl;
58 | public $Transform;
59 | public $FopTimeout;
60 |
61 | public function __construct($scope)
62 | {
63 | $this->Scope = $scope;
64 | }
65 |
66 | public function Token($mac) // => $token
67 | {
68 | $deadline = $this->Expires;
69 | if ($deadline == 0) {
70 | $deadline = 3600;
71 | }
72 | $deadline += time();
73 |
74 | $policy = array('scope' => $this->Scope, 'deadline' => $deadline);
75 | if (!empty($this->CallbackUrl)) {
76 | $policy['callbackUrl'] = $this->CallbackUrl;
77 | }
78 | if (!empty($this->CallbackBody)) {
79 | $policy['callbackBody'] = $this->CallbackBody;
80 | }
81 | if (!empty($this->ReturnUrl)) {
82 | $policy['returnUrl'] = $this->ReturnUrl;
83 | }
84 | if (!empty($this->ReturnBody)) {
85 | $policy['returnBody'] = $this->ReturnBody;
86 | }
87 | if (!empty($this->AsyncOps)) {
88 | $policy['asyncOps'] = $this->AsyncOps;
89 | }
90 | if (!empty($this->EndUser)) {
91 | $policy['endUser'] = $this->EndUser;
92 | }
93 | if (!empty($this->InsertOnly)) {
94 | $policy['exclusive'] = $this->InsertOnly;
95 | }
96 | if (!empty($this->DetectMime)) {
97 | $policy['detectMime'] = $this->DetectMime;
98 | }
99 | if (!empty($this->FsizeLimit)) {
100 | $policy['fsizeLimit'] = $this->FsizeLimit;
101 | }
102 | if (!empty($this->SaveKey)) {
103 | $policy['saveKey'] = $this->SaveKey;
104 | }
105 | if (!empty($this->PersistentOps)) {
106 | $policy['persistentOps'] = $this->PersistentOps;
107 | }
108 | if (!empty($this->PersistentNotifyUrl)) {
109 | $policy['persistentNotifyUrl'] = $this->PersistentNotifyUrl;
110 | }
111 | if (!empty($this->Transform)) {
112 | $policy['transform'] = $this->Transform;
113 | }
114 | if (!empty($this->FopTimeout)) {
115 | $policy['fopTimeout'] = $this->FopTimeout;
116 | }
117 |
118 | $b = json_encode($policy);
119 | return Qiniu_SignWithData($mac, $b);
120 | }
121 | }
122 |
123 | // ----------------------------------------------------------
124 | // class Qiniu_RS_EntryPath
125 |
126 | class Qiniu_RS_EntryPath
127 | {
128 | public $bucket;
129 | public $key;
130 |
131 | public function __construct($bucket, $key)
132 | {
133 | $this->bucket = $bucket;
134 | $this->key = $key;
135 | }
136 | }
137 |
138 | // ----------------------------------------------------------
139 | // class Qiniu_RS_EntryPathPair
140 |
141 | class Qiniu_RS_EntryPathPair
142 | {
143 | public $src;
144 | public $dest;
145 |
146 | public function __construct($src, $dest)
147 | {
148 | $this->src = $src;
149 | $this->dest = $dest;
150 | }
151 | }
152 |
153 | // ----------------------------------------------------------
154 |
155 | function Qiniu_RS_URIStat($bucket, $key)
156 | {
157 | return '/stat/' . Qiniu_Encode("$bucket:$key");
158 | }
159 |
160 | function Qiniu_RS_URIDelete($bucket, $key)
161 | {
162 | return '/delete/' . Qiniu_Encode("$bucket:$key");
163 | }
164 |
165 | function Qiniu_RS_URICopy($bucketSrc, $keySrc, $bucketDest, $keyDest)
166 | {
167 | return '/copy/' . Qiniu_Encode("$bucketSrc:$keySrc") . '/' . Qiniu_Encode("$bucketDest:$keyDest");
168 | }
169 |
170 | function Qiniu_RS_URIMove($bucketSrc, $keySrc, $bucketDest, $keyDest)
171 | {
172 | return '/move/' . Qiniu_Encode("$bucketSrc:$keySrc") . '/' . Qiniu_Encode("$bucketDest:$keyDest");
173 | }
174 |
175 | // ----------------------------------------------------------
176 |
177 | function Qiniu_RS_Stat($self, $bucket, $key) // => ($statRet, $error)
178 | {
179 | global $QINIU_RS_HOST;
180 | $uri = Qiniu_RS_URIStat($bucket, $key);
181 | return Qiniu_Client_Call($self, $QINIU_RS_HOST . $uri);
182 | }
183 |
184 | function Qiniu_RS_Delete($self, $bucket, $key) // => $error
185 | {
186 | global $QINIU_RS_HOST;
187 | $uri = Qiniu_RS_URIDelete($bucket, $key);
188 | return Qiniu_Client_CallNoRet($self, $QINIU_RS_HOST . $uri);
189 | }
190 |
191 | function Qiniu_RS_Move($self, $bucketSrc, $keySrc, $bucketDest, $keyDest) // => $error
192 | {
193 | global $QINIU_RS_HOST;
194 | $uri = Qiniu_RS_URIMove($bucketSrc, $keySrc, $bucketDest, $keyDest);
195 | return Qiniu_Client_CallNoRet($self, $QINIU_RS_HOST . $uri);
196 | }
197 |
198 | function Qiniu_RS_Copy($self, $bucketSrc, $keySrc, $bucketDest, $keyDest) // => $error
199 | {
200 | global $QINIU_RS_HOST;
201 | $uri = Qiniu_RS_URICopy($bucketSrc, $keySrc, $bucketDest, $keyDest);
202 | return Qiniu_Client_CallNoRet($self, $QINIU_RS_HOST . $uri);
203 | }
204 |
205 | // ----------------------------------------------------------
206 | // batch
207 |
208 | function Qiniu_RS_Batch($self, $ops) // => ($data, $error)
209 | {
210 | global $QINIU_RS_HOST;
211 | $url = $QINIU_RS_HOST . '/batch';
212 | $params = 'op=' . implode('&op=', $ops);
213 | return Qiniu_Client_CallWithForm($self, $url, $params);
214 | }
215 |
216 | function Qiniu_RS_BatchStat($self, $entryPaths)
217 | {
218 | $params = array();
219 | foreach ($entryPaths as $entryPath) {
220 | $params[] = Qiniu_RS_URIStat($entryPath->bucket, $entryPath->key);
221 | }
222 | return Qiniu_RS_Batch($self,$params);
223 | }
224 |
225 | function Qiniu_RS_BatchDelete($self, $entryPaths)
226 | {
227 | $params = array();
228 | foreach ($entryPaths as $entryPath) {
229 | $params[] = Qiniu_RS_URIDelete($entryPath->bucket, $entryPath->key);
230 | }
231 | return Qiniu_RS_Batch($self, $params);
232 | }
233 |
234 | function Qiniu_RS_BatchMove($self, $entryPairs)
235 | {
236 | $params = array();
237 | foreach ($entryPairs as $entryPair) {
238 | $src = $entryPair->src;
239 | $dest = $entryPair->dest;
240 | $params[] = Qiniu_RS_URIMove($src->bucket, $src->key, $dest->bucket, $dest->key);
241 | }
242 | return Qiniu_RS_Batch($self, $params);
243 | }
244 |
245 | function Qiniu_RS_BatchCopy($self, $entryPairs)
246 | {
247 | $params = array();
248 | foreach ($entryPairs as $entryPair) {
249 | $src = $entryPair->src;
250 | $dest = $entryPair->dest;
251 | $params[] = Qiniu_RS_URICopy($src->bucket, $src->key, $dest->bucket, $dest->key);
252 | }
253 | return Qiniu_RS_Batch($self, $params);
254 | }
255 |
256 | // ----------------------------------------------------------
257 |
258 |
--------------------------------------------------------------------------------
/sdk/rs_utils.php:
--------------------------------------------------------------------------------
1 | ($putRet, $err)
8 | {
9 | $putPolicy = new Qiniu_RS_PutPolicy("$bucket:$key");
10 | $upToken = $putPolicy->Token($self->Mac);
11 | return Qiniu_Put($upToken, $key, $body, $putExtra);
12 | }
13 |
14 | function Qiniu_RS_PutFile($self, $bucket, $key, $localFile, $putExtra) // => ($putRet, $err)
15 | {
16 | $putPolicy = new Qiniu_RS_PutPolicy("$bucket:$key");
17 | $upToken = $putPolicy->Token($self->Mac);
18 | return Qiniu_PutFile($upToken, $key, $localFile, $putExtra);
19 | }
20 |
21 | function Qiniu_RS_Rput($self, $bucket, $key, $body, $fsize, $putExtra) // => ($putRet, $err)
22 | {
23 | $putPolicy = new Qiniu_RS_PutPolicy("$bucket:$key");
24 | $upToken = $putPolicy->Token($self->Mac);
25 | if ($putExtra == null) {
26 | $putExtra = new Qiniu_Rio_PutExtra($bucket);
27 | } else {
28 | $putExtra->Bucket = $bucket;
29 | }
30 | return Qiniu_Rio_Put($upToken, $key, $body, $fsize, $putExtra);
31 | }
32 |
33 | function Qiniu_RS_RputFile($self, $bucket, $key, $localFile, $putExtra) // => ($putRet, $err)
34 | {
35 | $putPolicy = new Qiniu_RS_PutPolicy("$bucket:$key");
36 | $upToken = $putPolicy->Token($self->Mac);
37 | if ($putExtra == null) {
38 | $putExtra = new Qiniu_Rio_PutExtra($bucket);
39 | } else {
40 | $putExtra->Bucket = $bucket;
41 | }
42 | return Qiniu_Rio_PutFile($upToken, $key, $localFile, $putExtra);
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/sdk/rsf.php:
--------------------------------------------------------------------------------
1 | ($items, $markerOut, $err)
14 | {
15 | global $QINIU_RSF_HOST;
16 |
17 | $query = array('bucket' => $bucket);
18 | if (!empty($prefix)) {
19 | $query['prefix'] = $prefix;
20 | }
21 | if (!empty($marker)) {
22 | $query['marker'] = $marker;
23 | }
24 | if (!empty($limit)) {
25 | $query['limit'] = $limit;
26 | }
27 |
28 | $url = $QINIU_RSF_HOST . '/list?' . http_build_query($query);
29 | list($ret, $err) = Qiniu_Client_Call($self, $url);
30 | if ($err !== null) {
31 | return array(null, '', $err);
32 | }
33 |
34 | $items = $ret['items'];
35 | if (empty($ret['marker'])) {
36 | $markerOut = '';
37 | $err = Qiniu_RSF_EOF;
38 | } else {
39 | $markerOut = $ret['marker'];
40 | }
41 | return array($items, $markerOut, $err);
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/sdk/utils.php:
--------------------------------------------------------------------------------
1 |