Completed
Push — master ( bfc0cc...f0e226 )
by sabaku
04:05
created

Multi::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace Upyun\Api;
3
4
use GuzzleHttp\Psr7;
5
use GuzzleHttp\Client;
6
use Upyun\Config;
7
use Upyun\Signature;
8
use Upyun\Util;
9
10
class Multi {
11
    /**
12
     * @var Config
13
     */
14
    protected $config;
15
16
    protected $url;
17
18
    public function __construct(Config $config) {
19
        $this->config = $config;
20
        $this->url = ($this->config->useSsl ? 'https://' : 'http://') . Config::ED_FORM . '/'.
21
                     $this->config->bucketName;
22
    }
23
24
    /**
25
     * @param string $path 文件存储路径
26
     * @param Psr7\stream $stream 通过 `Psr7\stream_for` 方法格式化的流资源
27
     * @param string $fileHash 文件 md5 值
28
     * @param array $params 其他自定义参数
29
     *
30
     * @return Psr7\Response
31
     * @throws \Exception
32
     */
33
    public function upload($path, $stream, $fileHash, $params = []) {
34
        $path = '/' . ltrim($path, '/');
35
        $initInfo = $this->initRequest($path, $stream, $fileHash, $params);
36
        $blockStatus = $initInfo->status;
37
38
        $newBlockStatus = $blockStatus;
39
40
        for($blockId = 0; $blockId < $initInfo->blocks; $blockId++) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FOR keyword; 0 found
Loading history...
41
            if($blockStatus[$blockId] === 0) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
42
                $return = $this->blockUpload($initInfo, $blockId, $stream);
43
                $newBlockStatus = $return->status;
44
            }
45
        }
46
47
        if(array_sum($newBlockStatus) === $initInfo->blocks) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
48
            return $this->endRequest($initInfo, $params);
49
        } else {
50
            throw new \Exception(sprintf("chunk upload failed! current every block status is : [%s]", implode(',', $newBlockStatus)));
51
        }
52
    }
53
54
    private function initRequest($path, Psr7\Stream $stream, $fileHash, $params) {
55
        $metaData = array(
56
            'expiration' => time() + $this->config->blockExpiration,
57
            'file_blocks' => ceil($stream->getSize() / $this->config->maxBlockSize),
58
            'file_hash' => $fileHash,
59
            'file_size' => $stream->getSize(),
60
            'path' => $path
61
        );
62
63
        $metaData = array_merge($metaData, $params);
64
        $policy = Util::base64Json($metaData);
65
        $signature = Signature::getSignature(
66
            $this->config,
67
            $metaData,
68
            Signature::SIGN_MULTIPART
69
        );
70
        $postData = compact('policy', 'signature');
71
72
        $client = new Client();
73
        $response = $client->request('POST', $this->url, [
74
            'form_params' => $postData,
75
        ]);
76
77
        $initInfo = json_decode($response->getBody()->getContents());
78
        return $initInfo;
79
    }
80
81
    private function blockUpload($blocksInfo, $blockId, Psr7\Stream $stream, $params = []) {
82
        $startPosition = $blockId * $this->config->maxBlockSize;
83
        $endPosition   = $blockId >= $blocksInfo->blocks - 1 ? $stream->getSize() : $startPosition + $this->config->maxBlockSize;
84
85
        $stream->seek($startPosition);
86
87
        $fileBlock = $stream->read($endPosition - $startPosition);
88
89
        $metaData = array(
90
            'save_token' => $blocksInfo->save_token,
91
            'expiration' => $blocksInfo->expired_at,
92
            'block_index' => $blockId,
93
            'block_hash' => md5($fileBlock),
94
        );
95
        $metaData = array_merge($metaData, $params);
96
        $postData['policy'] = Util::base64Json($metaData);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$postData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $postData = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
97
        $postData['signature'] = Signature::getSignature(
98
            $this->config,
99
            $metaData,
100
            Signature::SIGN_MULTIPART,
101
            $blocksInfo->token_secret
102
        );
103
104
        $multipart = [];
105
        foreach($postData as $key => $value) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FOREACH keyword; 0 found
Loading history...
106
           $multipart[] = ['name' => $key, 'contents' => $value];
107
        }
108
        $multipart[] = [
109
            'name' => 'file',
110
            'contents' => $fileBlock,
111
            'filename' => 'file',  //this value must be file
112
            'headers' => ['Content-Type' => 'application/octet-stream']
113
        ];
114
        $postData['file'] = $fileBlock;
115
116
        $client = new Client();
117
        $response = $client->request('POST', $this->url, [
118
            'multipart' => $multipart,
119
        ]);
120
121
        return json_decode($response->getBody()->getContents());
122
    }
123
124
    private function endRequest($initInfo, $data = array()) {
125
        $metaData['save_token'] = $initInfo->save_token;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$metaData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $metaData = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
126
        $metaData['expiration'] = $initInfo->expired_at;
127
128
        $metaData = array_merge($metaData, $data);
129
        $policy = Util::base64Json($metaData);
130
        $signature = Signature::getSignature(
131
            $this->config,
132
            $metaData,
133
            Signature::SIGN_MULTIPART,
134
            $initInfo->token_secret
135
        );
136
        $postData = compact('policy', 'signature');
137
138
        $client = new Client();
139
        $response = $client->request('POST', $this->url, [
140
            'form_params' => $postData
141
        ]);
142
        return $response;
143
    }
144
}
145