| 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); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 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($fname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 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 |  |  |                 list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |                 if ($err != null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |                     return array(null, $err); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |                 $upHostBackup = $this->config->getUpBackupHost($accessKey, $bucket); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |                 $this->host = $upHostBackup; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 6 |  |             if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 | 1 |  |                 $response = $this->makeBlock($data, $blockSize); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 | 1 |  |                 $ret = $response->json(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 1 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 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($fname); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 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($fname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 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 |  |         $url .= '/fname/' . \Qiniu\base64_urlSafeEncode($fname); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 6 |  |         if (!empty($this->params)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |             foreach ($this->params as $key => $value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |                 $val = \Qiniu\base64_urlSafeEncode($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |                 $url .= "/$key/$val"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 6 |  |         return $url; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |      * 创建文件 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 | 6 |  |     private function makeFile($fname) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 | 6 |  |         $url = $this->fileUrl($fname); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 | 6 |  |         $body = implode(',', $this->contexts); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 | 6 |  |         $response = $this->post($url, $body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 | 6 |  |         if ($response->needRetry()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |             $response = $this->post($url, $body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 | 6 |  |         if (!$response->ok()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |             return array(null, new Error($this->currentUrl, $response)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 | 6 |  |         return array($response->json(), null); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 | 6 |  |     private function post($url, $data) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 | 6 |  |         $this->currentUrl = $url; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 | 6 |  |         $headers = array('Authorization' => 'UpToken ' . $this->upToken); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 | 6 |  |         return Client::post($url, $data, $headers); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 161 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 162 | 6 |  |     private function blockSize($uploaded) | 
            
                                                        
            
                                    
            
            
                | 163 |  |  |     { | 
            
                                                        
            
                                    
            
            
                | 164 | 6 |  |         if ($this->size < $uploaded + Config::BLOCK_SIZE) { | 
            
                                                        
            
                                    
            
            
                | 165 | 6 |  |             return $this->size - $uploaded; | 
            
                                                        
            
                                    
            
            
                | 166 |  |  |         } | 
            
                                                        
            
                                    
            
            
                | 167 | 6 |  |         return Config::BLOCK_SIZE; | 
            
                                                        
            
                                    
            
            
                | 168 |  |  |     } | 
            
                                                        
            
                                    
            
            
                | 169 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 170 |  |  |  |