mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2025-04-06 03:58:04 +08:00
169 lines
4.8 KiB
PHP
169 lines
4.8 KiB
PHP
<?php
|
|
namespace Qiniu\Storage;
|
|
|
|
use Qiniu\Config;
|
|
use Qiniu\Http\Client;
|
|
use Qiniu\Http\Error;
|
|
|
|
/**
|
|
* 断点续上传类, 该类主要实现了断点续上传中的分块上传,
|
|
* 以及相应地创建块和创建文件过程.
|
|
*
|
|
* @link http://developer.qiniu.com/docs/v6/api/reference/up/mkblk.html
|
|
* @link http://developer.qiniu.com/docs/v6/api/reference/up/mkfile.html
|
|
*/
|
|
final class ResumeUploader
|
|
{
|
|
private $upToken;
|
|
private $key;
|
|
private $inputStream;
|
|
private $size;
|
|
private $params;
|
|
private $mime;
|
|
private $contexts;
|
|
private $host;
|
|
private $currentUrl;
|
|
private $config;
|
|
|
|
/**
|
|
* 上传二进制流到七牛
|
|
*
|
|
* @param $upToken 上传凭证
|
|
* @param $key 上传文件名
|
|
* @param $inputStream 上传二进制流
|
|
* @param $size 上传流的大小
|
|
* @param $params 自定义变量
|
|
* @param $mime 上传数据的mimeType
|
|
*
|
|
* @link http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
|
|
*/
|
|
public function __construct(
|
|
$upToken,
|
|
$key,
|
|
$inputStream,
|
|
$size,
|
|
$params,
|
|
$mime,
|
|
$config
|
|
) {
|
|
|
|
$this->upToken = $upToken;
|
|
$this->key = $key;
|
|
$this->inputStream = $inputStream;
|
|
$this->size = $size;
|
|
$this->params = $params;
|
|
$this->mime = $mime;
|
|
$this->contexts = array();
|
|
$this->config = $config;
|
|
|
|
list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
|
|
if ($err != null) {
|
|
return array(null, $err);
|
|
}
|
|
|
|
$upHost = $config->getUpHost($accessKey, $bucket);
|
|
if ($err != null) {
|
|
throw new \Exception($err->message(), 1);
|
|
}
|
|
$this->host = $upHost;
|
|
}
|
|
|
|
/**
|
|
* 上传操作
|
|
*/
|
|
public function upload()
|
|
{
|
|
$uploaded = 0;
|
|
while ($uploaded < $this->size) {
|
|
$blockSize = $this->blockSize($uploaded);
|
|
$data = fread($this->inputStream, $blockSize);
|
|
if ($data === false) {
|
|
throw new \Exception("file read failed", 1);
|
|
}
|
|
$crc = \Qiniu\crc32_data($data);
|
|
$response = $this->makeBlock($data, $blockSize);
|
|
$ret = null;
|
|
if ($response->ok() && $response->json() != null) {
|
|
$ret = $response->json();
|
|
}
|
|
if ($response->statusCode < 0) {
|
|
list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken);
|
|
if ($err != null) {
|
|
return array(null, $err);
|
|
}
|
|
|
|
$upHostBackup = $this->config->getUpBackupHost($accessKey, $bucket);
|
|
$this->host = $upHostBackup;
|
|
}
|
|
if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
|
|
$response = $this->makeBlock($data, $blockSize);
|
|
$ret = $response->json();
|
|
}
|
|
|
|
if (!$response->ok() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
|
|
return array(null, new Error($this->currentUrl, $response));
|
|
}
|
|
array_push($this->contexts, $ret['ctx']);
|
|
$uploaded += $blockSize;
|
|
}
|
|
return $this->makeFile();
|
|
}
|
|
|
|
/**
|
|
* 创建块
|
|
*/
|
|
private function makeBlock($block, $blockSize)
|
|
{
|
|
$url = $this->host . '/mkblk/' . $blockSize;
|
|
return $this->post($url, $block);
|
|
}
|
|
|
|
private function fileUrl()
|
|
{
|
|
$url = $this->host . '/mkfile/' . $this->size;
|
|
$url .= '/mimeType/' . \Qiniu\base64_urlSafeEncode($this->mime);
|
|
if ($this->key != null) {
|
|
$url .= '/key/' . \Qiniu\base64_urlSafeEncode($this->key);
|
|
}
|
|
if (!empty($this->params)) {
|
|
foreach ($this->params as $key => $value) {
|
|
$val = \Qiniu\base64_urlSafeEncode($value);
|
|
$url .= "/$key/$val";
|
|
}
|
|
}
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* 创建文件
|
|
*/
|
|
private function makeFile()
|
|
{
|
|
$url = $this->fileUrl();
|
|
$body = implode(',', $this->contexts);
|
|
$response = $this->post($url, $body);
|
|
if ($response->needRetry()) {
|
|
$response = $this->post($url, $body);
|
|
}
|
|
if (!$response->ok()) {
|
|
return array(null, new Error($this->currentUrl, $response));
|
|
}
|
|
return array($response->json(), null);
|
|
}
|
|
|
|
private function post($url, $data)
|
|
{
|
|
$this->currentUrl = $url;
|
|
$headers = array('Authorization' => 'UpToken ' . $this->upToken);
|
|
return Client::post($url, $data, $headers);
|
|
}
|
|
|
|
private function blockSize($uploaded)
|
|
{
|
|
if ($this->size < $uploaded + Config::BLOCK_SIZE) {
|
|
return $this->size - $uploaded;
|
|
}
|
|
return Config::BLOCK_SIZE;
|
|
}
|
|
}
|