Skip to content

Commit 14bf633

Browse files
committed
Merge pull request #24 from qiniu/develop
Release v6.1.1
2 parents 20962ce + 539f8d2 commit 14bf633

File tree

8 files changed

+315
-7
lines changed

8 files changed

+315
-7
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
## CHANGE LOG
22

3+
### v6.1.1
4+
5+
2013-07-04 issue [#24](https://github.com/qiniu/api/pull/24)
6+
7+
- 支持断点续上传(`Qiniu_RS_Rput`, `Qiniu_RS_RputFile`)
8+
9+
310
### v6.1.0
411

512
2013-07-04 issue [#22](https://github.com/qiniu/api/pull/22)

qiniu/io.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Qiniu_PutExtra
1414
public $CheckCrc = 0;
1515
}
1616

17-
function Qiniu_Put($upToken, $key, $body, $putExtra) // => ($data, $err)
17+
function Qiniu_Put($upToken, $key, $body, $putExtra) // => ($putRet, $err)
1818
{
1919
global $QINIU_UP_HOST;
2020

@@ -39,7 +39,7 @@ function Qiniu_Put($upToken, $key, $body, $putExtra) // => ($data, $err)
3939
return Qiniu_Client_CallWithMultipartForm($client, $QINIU_UP_HOST, $fields, $files);
4040
}
4141

42-
function Qiniu_PutFile($upToken, $key, $localFile, $putExtra) // => ($data, $err)
42+
function Qiniu_PutFile($upToken, $key, $localFile, $putExtra) // => ($putRet, $err)
4343
{
4444
global $QINIU_UP_HOST;
4545

@@ -67,3 +67,5 @@ function Qiniu_PutFile($upToken, $key, $localFile, $putExtra) // => ($data, $err
6767
return Qiniu_Client_CallWithForm($client, $QINIU_UP_HOST, $fields, 'multipart/form-data');
6868
}
6969

70+
// ----------------------------------------------------------
71+

qiniu/resumable_io.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
require_once("http.php");
4+
require_once("auth_digest.php");
5+
6+
// ----------------------------------------------------------
7+
// class Qiniu_Rio_PutExtra
8+
9+
class Qiniu_Rio_PutExtra
10+
{
11+
public $Bucket = null; // 必选(未来会没有这个字段)。
12+
public $Params = null;
13+
public $MimeType = null;
14+
public $ChunkSize = 0; // 可选。每次上传的Chunk大小
15+
public $TryTimes = 0; // 可选。尝试次数
16+
public $Progresses = null; // 可选。上传进度:[]BlkputRet
17+
public $Notify = null; // 进度通知:func(blkIdx int, blkSize int, ret *BlkputRet)
18+
public $NotifyErr = null; // 错误通知:func(blkIdx int, blkSize int, err error)
19+
20+
public function __construct($bucket = null) {
21+
$this->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+
function Qiniu_Rio_Mkfile($self, $host, $key, $fsize, $extra) // => ($putRet, $err)
63+
{
64+
$entry = $extra->Bucket . ':' . $key;
65+
$url = $host . '/rs-mkfile/' . Qiniu_Encode($entry) . '/fsize/' . $fsize;
66+
67+
if (!empty($extra->MimeType)) {
68+
$url .= '/mimeType/' . Qiniu_Encode($extra->MimeType);
69+
}
70+
71+
$ctxs = array();
72+
foreach ($extra->Progresses as $prog) {
73+
$ctxs []= $prog['ctx'];
74+
}
75+
$body = implode(',', $ctxs);
76+
77+
return Qiniu_Client_CallWithForm($self, $url, $body, 'text/plain');
78+
}
79+
80+
// ----------------------------------------------------------
81+
// class Qiniu_Rio_UploadClient
82+
83+
class Qiniu_Rio_UploadClient
84+
{
85+
public $uptoken;
86+
87+
public function __construct($uptoken)
88+
{
89+
$this->uptoken = $uptoken;
90+
}
91+
92+
public function RoundTrip($req) // => ($resp, $error)
93+
{
94+
$token = $this->uptoken;
95+
$req->Header['Authorization'] = "UpToken $token";
96+
return Qiniu_Client_do($req);
97+
}
98+
}
99+
100+
// ----------------------------------------------------------
101+
// class Qiniu_Rio_Put/PutFile
102+
103+
function Qiniu_Rio_Put($upToken, $key, $body, $fsize, $putExtra) // => ($putRet, $err)
104+
{
105+
global $QINIU_UP_HOST;
106+
107+
$self = new Qiniu_Rio_UploadClient($upToken);
108+
109+
$progresses = array();
110+
$host = $QINIU_UP_HOST;
111+
$uploaded = 0;
112+
while ($uploaded < $fsize) {
113+
if ($fsize < $uploaded + QINIU_RIO_BLOCK_SIZE) {
114+
$bsize = $fsize - $uploaded;
115+
} else {
116+
$bsize = QINIU_RIO_BLOCK_SIZE;
117+
}
118+
list($blkputRet, $err) = Qiniu_Rio_Mkblock($self, $host, $body, $bsize);
119+
$host = $blkputRet['host'];
120+
$uploaded += $bsize;
121+
$progresses []= $blkputRet;
122+
}
123+
124+
$putExtra->Progresses = $progresses;
125+
return Qiniu_Rio_Mkfile($self, $host, $key, $fsize, $putExtra);
126+
}
127+
128+
function Qiniu_Rio_PutFile($upToken, $key, $localFile, $putExtra) // => ($putRet, $err)
129+
{
130+
$fp = fopen($localFile, 'rb');
131+
if ($fp === false) {
132+
$err = Qiniu_NewError(0, 'fopen failed');
133+
return array(null, $err);
134+
}
135+
136+
$fi = fstat($fp);
137+
$result = Qiniu_Rio_Put($upToken, $key, $fp, $fi['size'], $putExtra);
138+
fclose($fp);
139+
return $result;
140+
}
141+
142+
// ----------------------------------------------------------
143+

qiniu/rs.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,8 @@ function Qiniu_RS_Copy($self, $bucketSrc, $keySrc, $bucketDest, $keyDest) // =>
170170
return Qiniu_Client_CallNoRet($self, $QINIU_RS_HOST . $uri);
171171
}
172172

173-
174173
// ----------------------------------------------------------
175-
//batch
174+
// batch
176175

177176
function Qiniu_RS_Batch($self, $ops) // => ($data, $error)
178177
{
@@ -222,3 +221,5 @@ function Qiniu_RS_BatchCopy($self, $entryPairs)
222221
return Qiniu_RS_Batch($self, $params);
223222
}
224223

224+
// ----------------------------------------------------------
225+

qiniu/rs_utils.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,43 @@
22

33
require_once("rs.php");
44
require_once("io.php");
5+
require_once("resumable_io.php");
56

6-
function Qiniu_RS_Put($self, $bucket, $key, $body, $putExtra) // => ($data, $err)
7+
function Qiniu_RS_Put($self, $bucket, $key, $body, $putExtra) // => ($putRet, $err)
78
{
89
$putPolicy = new Qiniu_RS_PutPolicy("$bucket:$key");
910
$upToken = $putPolicy->Token($self->Mac);
1011
return Qiniu_Put($upToken, $key, $body, $putExtra);
1112
}
1213

13-
function Qiniu_RS_PutFile($self, $bucket, $key, $localFile, $putExtra) // => ($data, $err)
14+
function Qiniu_RS_PutFile($self, $bucket, $key, $localFile, $putExtra) // => ($putRet, $err)
1415
{
1516
$putPolicy = new Qiniu_RS_PutPolicy("$bucket:$key");
1617
$upToken = $putPolicy->Token($self->Mac);
1718
return Qiniu_PutFile($upToken, $key, $localFile, $putExtra);
1819
}
1920

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+

tests/RioTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
require_once("bootstrap.php");
4+
5+
class RioTest extends PHPUnit_Framework_TestCase
6+
{
7+
public $bucket;
8+
public $client;
9+
10+
public function setUp()
11+
{
12+
initKeys();
13+
$this->client = new Qiniu_MacHttpClient(null);
14+
$this->bucket = getenv("QINIU_BUCKET_NAME");
15+
}
16+
17+
public function testMockReader()
18+
{
19+
$reader = new MockReader;
20+
list($data) = $reader->Read(5);
21+
$this->assertEquals($data, "ABCDE");
22+
23+
list($data) = $reader->Read(27);
24+
$this->assertEquals($data, "FGHIJKLMNOPQRSTUVWXYZABCDEF");
25+
}
26+
27+
public function testPut()
28+
{
29+
$key = 'testRioPut' . getTid();
30+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
31+
32+
$putPolicy = new Qiniu_RS_PutPolicy($this->bucket);
33+
$upToken = $putPolicy->Token(null);
34+
$putExtra = new Qiniu_Rio_PutExtra($this->bucket);
35+
$reader = new MockReader;
36+
list($ret, $err) = Qiniu_Rio_Put($upToken, $key, $reader, 5, $putExtra);
37+
$this->assertNull($err);
38+
$this->assertEquals($ret['hash'], "Fnvgeq9GDVk6Mj0Nsz2gW2S_3LOl");
39+
var_dump($ret);
40+
41+
list($ret, $err) = Qiniu_RS_Stat($this->client, $this->bucket, $key);
42+
$this->assertNull($err);
43+
var_dump($ret);
44+
45+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
46+
$this->assertNull($err);
47+
}
48+
49+
public function testLargePut()
50+
{
51+
$key = 'testRioLargePut' . getTid();
52+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
53+
54+
$putPolicy = new Qiniu_RS_PutPolicy($this->bucket);
55+
$upToken = $putPolicy->Token(null);
56+
$putExtra = new Qiniu_Rio_PutExtra($this->bucket);
57+
$reader = new MockReader;
58+
list($ret, $err) = Qiniu_Rio_Put($upToken, $key, $reader, QINIU_RIO_BLOCK_SIZE + 5, $putExtra);
59+
$this->assertNull($err);
60+
$this->assertEquals($ret['hash'], "lgQEOCZ8Ievliq8XOfZmWTndgOll");
61+
var_dump($ret);
62+
63+
list($ret, $err) = Qiniu_RS_Stat($this->client, $this->bucket, $key);
64+
$this->assertNull($err);
65+
var_dump($ret);
66+
67+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
68+
$this->assertNull($err);
69+
}
70+
}
71+

tests/RsUtilsTest.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,43 @@ public function setUp()
1414
$this->bucket = getenv("QINIU_BUCKET_NAME");
1515
}
1616

17+
public function testRput()
18+
{
19+
$key = 'tmp/testRput' . getTid();
20+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
21+
22+
$reader = new MockReader;
23+
list($ret, $err) = Qiniu_RS_Rput($this->client, $this->bucket, $key, $reader, 5, null);
24+
$this->assertNull($err);
25+
var_dump($ret);
26+
$this->assertEquals($ret['hash'], "Fnvgeq9GDVk6Mj0Nsz2gW2S_3LOl");
27+
28+
list($ret, $err) = Qiniu_RS_Stat($this->client, $this->bucket, $key);
29+
$this->assertNull($err);
30+
var_dump($ret);
31+
32+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
33+
$this->assertNull($err);
34+
}
35+
36+
public function testRputFile()
37+
{
38+
$key = 'tmp/testRputFile' . getTid();
39+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
40+
41+
list($ret, $err) = Qiniu_RS_RputFile($this->client, $this->bucket, $key, __file__, null);
42+
$this->assertNull($err);
43+
var_dump($ret);
44+
$this->assertArrayHasKey('hash', $ret);
45+
46+
list($ret, $err) = Qiniu_RS_Stat($this->client, $this->bucket, $key);
47+
$this->assertNull($err);
48+
var_dump($ret);
49+
50+
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
51+
$this->assertNull($err);
52+
}
53+
1754
public function testPutFile()
1855
{
1956
$key = 'tmp/testPutFile' . getTid();
@@ -39,7 +76,7 @@ public function testPut()
3976
$key = 'tmp/testPut' . getTid();
4077
$err = Qiniu_RS_Delete($this->client, $this->bucket, $key);
4178

42-
list($ret, $err) = Qiniu_RS_Put($this->client, $this->bucket, $key, "hello world!", null);
79+
list($ret, $err) = Qiniu_RS_Put($this->client, $this->bucket, $key, 'hello world!', null);
4380
$this->assertNull($err);
4481
$this->assertArrayHasKey('hash', $ret);
4582
var_dump($ret);

tests/bootstrap.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,25 @@ function getTid() {
2424
return $tid;
2525
}
2626

27+
class MockReader
28+
{
29+
private $off = 0;
30+
31+
public function __construct($off = 0)
32+
{
33+
$this->off = $off;
34+
}
35+
36+
public function Read($bytes) // => ($data, $err)
37+
{
38+
$off = $this->off;
39+
$data = '';
40+
for ($i = 0; $i < $bytes; $i++) {
41+
$data .= chr(65 + ($off % 26)); // ord('A') = 65
42+
$off++;
43+
}
44+
$this->off = $off;
45+
return array($data, null);
46+
}
47+
}
48+

0 commit comments

Comments
 (0)