Completed
Pull Request — master (#190)
by r
11:40 queued 09:03
created

ResumeUploader::upload()   C

Complexity

Conditions 12
Paths 18

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 14.8092

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 12
eloc 22
c 2
b 0
f 0
nc 18
nop 0
dl 0
loc 31
ccs 19
cts 26
cp 0.7308
crap 14.8092
rs 5.1612

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 6
        $this->upToken = $upToken;
50 6
        $this->key = $key;
51 6
        $this->inputStream = $inputStream;
52 6
        $this->size = $size;
53 6
        $this->params = $params;
54 6
        $this->mime = $mime;
55 6
        $this->contexts = array();
56 6
        $this->config = $config;
57 6
        $this->host = $config->zone->getUpHostByToken($upToken);
58 6
    }
59
60
    /**
61
     * 上传操作
62
     */
63 6
    public function upload()
64
    {
65 6
        $uploaded = 0;
66 6
        while ($uploaded < $this->size) {
67 6
            $blockSize = $this->blockSize($uploaded);
68 6
            $data = fread($this->inputStream, $blockSize);
69 6
            if ($data === false) {
70
                throw new \Exception("file read failed", 1);
71
            }
72 6
            $crc = \Qiniu\crc32_data($data);
73 6
            $response = $this->makeBlock($data, $blockSize);
74 6
            $ret = null;
75 6
            if ($response->ok() && $response->json() != null) {
76 6
                $ret = $response->json();
77 4
            }
78 6
            if ($response->statusCode < 0) {
79
                $this->host = $this->config->zone->getBackupUpHostByToken($this->upToken);
80
            }
81 6
            if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
82
                $response = $this->makeBlock($data, $blockSize);
83
                $ret = $response->json();
84
            }
85
86 6
            if (! $response->ok() || !isset($ret['crc32'])|| $crc != $ret['crc32']) {
87
                return array(null, new Error($this->currentUrl, $response));
88
            }
89 6
            array_push($this->contexts, $ret['ctx']);
90 6
            $uploaded += $blockSize;
91 4
        }
92 6
        return $this->makeFile();
93
    }
94
95
    /**
96
     * 创建块
97
     */
98 6
    private function makeBlock($block, $blockSize)
99
    {
100 6
        $url = $this->host . '/mkblk/' . $blockSize;
101 6
        return $this->post($url, $block);
102
    }
103
104 6
    private function fileUrl()
105
    {
106 6
        $url = $this->host . '/mkfile/' . $this->size;
107 6
        $url .= '/mimeType/' . \Qiniu\base64_urlSafeEncode($this->mime);
108 6
        if ($this->key != null) {
109 6
            $url .= '/key/' . \Qiniu\base64_urlSafeEncode($this->key);
110 4
        }
111 6
        if (!empty($this->params)) {
112
            foreach ($this->params as $key => $value) {
113
                $val =  \Qiniu\base64_urlSafeEncode($value);
114
                $url .= "/$key/$val";
115
            }
116
        }
117 6
        return $url;
118
    }
119
120
    /**
121
     * 创建文件
122
     */
123 6
    private function makeFile()
124
    {
125 6
        $url = $this->fileUrl();
126 6
        $body = implode(',', $this->contexts);
127 6
        $response = $this->post($url, $body);
128 6
        if ($response->needRetry()) {
129
            $response = $this->post($url, $body);
130
        }
131 6
        if (! $response->ok()) {
132
            return array(null, new Error($this->currentUrl, $response));
133
        }
134 6
        return array($response->json(), null);
135
    }
136
137 6
    private function post($url, $data)
138
    {
139 6
        $this->currentUrl = $url;
140 6
        $headers = array('Authorization' => 'UpToken ' . $this->upToken);
141 6
        return Client::post($url, $data, $headers);
142
    }
143
144 6
    private function blockSize($uploaded)
145
    {
146 6
        if ($this->size < $uploaded + Config::BLOCK_SIZE) {
147 6
            return $this->size - $uploaded;
148
        }
149 6
        return  Config::BLOCK_SIZE;
150
    }
151
}
152