Completed
Push — master ( 55f13a...79290f )
by
unknown
24:57 queued 23:17
created

ResumeUploader   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 83.95%

Importance

Changes 0
Metric Value
dl 0
loc 154
ccs 68
cts 81
cp 0.8395
rs 10
c 0
b 0
f 0
wmc 27
lcom 1
cbo 3

7 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 30 3
C upload() 0 37 13
A makeBlock() 0 5 1
A fileUrl() 0 15 4
A makeFile() 0 13 3
A post() 0 6 1
A blockSize() 0 7 2
1
<?php
2
namespace Qiniu\Storage;
3
4
use Qiniu\Config;
5
use Qiniu\Http\Client;
6
use Qiniu\Http\Error;
7
8
/**
9
 * 断点续上传类, 该类主要实现了断点续上传中的分块上传,
10
 * 以及相应地创建块和创建文件过程.
11
 *
12
 * @link http://developer.qiniu.com/docs/v6/api/reference/up/mkblk.html
13
 * @link http://developer.qiniu.com/docs/v6/api/reference/up/mkfile.html
14
 */
15
final class ResumeUploader
16
{
17
    private $upToken;
18
    private $key;
19
    private $inputStream;
20
    private $size;
21
    private $params;
22
    private $mime;
23
    private $contexts;
24
    private $host;
25
    private $currentUrl;
26
    private $config;
27
28
    /**
29
     * 上传二进制流到七牛
30
     *
31
     * @param $upToken    上传凭证
32
     * @param $key        上传文件名
33
     * @param $inputStream 上传二进制流
34
     * @param $size       上传流的大小
35
     * @param $params     自定义变量
36
     * @param $mime       上传数据的mimeType
37
     *
38
     * @link http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
39
     */
40 6
    public function __construct(
41
        $upToken,
42
        $key,
43
        $inputStream,
44
        $size,
45
        $params,
46
        $mime,
47
        $config
48
    ) {
49
50 6
        $this->upToken = $upToken;
51 6
        $this->key = $key;
52 6
        $this->inputStream = $inputStream;
53 6
        $this->size = $size;
54 6
        $this->params = $params;
55 6
        $this->mime = $mime;
56 6
        $this->contexts = array();
57 6
        $this->config = $config;
58
59 6
        list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
60 6
        if ($err != null) {
61
            return array(null, $err);
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
62
        }
63
64 6
        $upHost = $config->getUpHost($accessKey, $bucket);
65 6
        if ($err != null) {
66
            throw new \Exception($err->message(), 1);
67
        }
68 6
        $this->host = $upHost;
69 6
    }
70
71
    /**
72
     * 上传操作
73
     */
74 6
    public function upload()
75
    {
76 6
        $uploaded = 0;
77 6
        while ($uploaded < $this->size) {
78 6
            $blockSize = $this->blockSize($uploaded);
79 6
            $data = fread($this->inputStream, $blockSize);
80 6
            if ($data === false) {
81
                throw new \Exception("file read failed", 1);
82
            }
83 6
            $crc = \Qiniu\crc32_data($data);
84 6
            $response = $this->makeBlock($data, $blockSize);
85 6
            $ret = null;
86 6
            if ($response->ok() && $response->json() != null) {
87 6
                $ret = $response->json();
88 6
            }
89 6
            if ($response->statusCode < 0) {
90 3
                list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken);
91 3
                if ($err != null) {
92
                    return array(null, $err);
93
                }
94
95 3
                $upHostBackup = $this->config->getUpBackupHost($accessKey, $bucket);
96 3
                $this->host = $upHostBackup;
97 3
            }
98 6
            if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
99 3
                $response = $this->makeBlock($data, $blockSize);
100 3
                $ret = $response->json();
101 3
            }
102
103 6
            if (!$response->ok() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
104
                return array(null, new Error($this->currentUrl, $response));
105
            }
106 6
            array_push($this->contexts, $ret['ctx']);
107 6
            $uploaded += $blockSize;
108 6
        }
109 6
        return $this->makeFile();
110
    }
111
112
    /**
113
     * 创建块
114
     */
115 6
    private function makeBlock($block, $blockSize)
116
    {
117 6
        $url = $this->host . '/mkblk/' . $blockSize;
118 6
        return $this->post($url, $block);
119
    }
120
121 6
    private function fileUrl()
122
    {
123 6
        $url = $this->host . '/mkfile/' . $this->size;
124 6
        $url .= '/mimeType/' . \Qiniu\base64_urlSafeEncode($this->mime);
125 6
        if ($this->key != null) {
126 6
            $url .= '/key/' . \Qiniu\base64_urlSafeEncode($this->key);
127 6
        }
128 6
        if (!empty($this->params)) {
129
            foreach ($this->params as $key => $value) {
130
                $val = \Qiniu\base64_urlSafeEncode($value);
131
                $url .= "/$key/$val";
132
            }
133
        }
134 6
        return $url;
135
    }
136
137
    /**
138
     * 创建文件
139
     */
140 6
    private function makeFile()
141
    {
142 6
        $url = $this->fileUrl();
143 6
        $body = implode(',', $this->contexts);
144 6
        $response = $this->post($url, $body);
145 6
        if ($response->needRetry()) {
146
            $response = $this->post($url, $body);
147
        }
148 6
        if (!$response->ok()) {
149
            return array(null, new Error($this->currentUrl, $response));
150
        }
151 6
        return array($response->json(), null);
152
    }
153
154 6
    private function post($url, $data)
155
    {
156 6
        $this->currentUrl = $url;
157 6
        $headers = array('Authorization' => 'UpToken ' . $this->upToken);
158 6
        return Client::post($url, $data, $headers);
159
    }
160
161 6
    private function blockSize($uploaded)
162
    {
163 6
        if ($this->size < $uploaded + Config::BLOCK_SIZE) {
164 6
            return $this->size - $uploaded;
165
        }
166 6
        return Config::BLOCK_SIZE;
167
    }
168
}
169