<?php
 namespace ModStart\Data\Storage; use ModStart\Core\Input\Response; use ModStart\Core\Util\PathUtil; use ModStart\Data\AbstractDataStorage; use OSS\OssClient; class AliyunOssDataStorage extends AbstractDataStorage { private $client; private $bucket; public function init() { $this->client = new OssClient( $this->option['aliyunAccessKeyId'], $this->option['aliyunAccessKeySecret'], $this->option['aliyunEndpoint'] ); $this->bucket = $this->option['aliyunBucket']; } public function has($file) { try { $ret = $this->client->getObjectMeta($this->bucket, $file); if (empty($ret['etag'])) { return false; } return true; } catch (\Exception $e) { return false; } } public function move($from, $to) { $this->client->copyObject($this->bucket, $from, $this->bucket, $to); $this->client->deleteObject($this->bucket, $from); } public function delete($file) { $ret = $this->client->deleteObject($this->bucket, $file); } public function put($file, $content) { $this->client->putObject($this->bucket, $file, $content); } public function get($file) { return $this->client->getObject($this->bucket, $file); } public function size($file) { exit('TODO'); $ret = $this->client->getObjectMeta($this->bucket, $file); return $ret['size']; } public function multiPartInit($param) { $token = $this->multiPartInitToken($param); $uploadId = $this->client->initiateMultipartUpload($this->bucket, $token['fullPath']); if (empty($uploadId)) { return Response::generate(-1, 'MultiPartInit init fail'); } $token['multiPartUploadId'] = $uploadId; $this->uploadChunkTokenAndUpdateToken($token); return Response::generate(0, 'ok', $token); } public function multiPartUpload($param) { $token = $this->multiPartInitToken($param); $input = $param['input']; $category = $param['category']; $data = []; if (!isset($input['chunks'])) { $input['chunks'] = 1; } if (!isset($input['chunk'])) { $input['chunk'] = 0; } if (empty($input['file'])) { return Response::generate(-1, 'MultiPartUpload file empty'); } $data['chunks'] = $input['chunks']; $data['chunk'] = $input['chunk']; $data['file'] = $input['file']; $hash = $token['hash']; $hashFile = self::DATA_CHUNK . '/data/' . $hash; if ($data['chunk'] < $data['chunks']) { if (!isset($token['multiPartUploadId']) && $data['chunk'] === 0 && $data['chunks'] === 1) { $uploadRet = $this->client->uploadFile($this->bucket, $token['fullPath'], $data['file']->getRealPath()); if (empty($uploadRet['info']['url'])) { return Response::generate(-1, 'MultiPartUpload upload file fail'); } $dataTemp = $this->repository->addTemp($category, $token['path'], $token['name'], $token['size']); $data['data'] = $dataTemp; $data['path'] = $token['fullPath']; $data['finished'] = true; } else { $options = [ OssClient::OSS_FILE_UPLOAD => $data['file']->getRealPath(), OssClient::OSS_PART_NUM => $data['chunk'] + 1, ]; $eTag = $this->client->uploadPart($this->bucket, $token['fullPath'], $token['multiPartUploadId'], $options); if (empty($eTag)) { return Response::generate(-1, 'MultiPartUpload upload part fail'); } if (empty($token['partIds'])) { $token['partIds'] = []; } $token['partIds'][] = [ 'PartNumber' => $data['chunk'] + 1, 'ETag' => $eTag, 'Size' => filesize($data['file']->getRealPath()), ]; $token['chunkUploaded'] = $data['chunk'] + 1; $this->uploadChunkTokenAndUpdateToken($token); $data['finished'] = false; if ($token['chunkUploaded'] == $data['chunks']) { $ret = $this->client->completeMultipartUpload($this->bucket, $token['fullPath'], $token['multiPartUploadId'], $token['partIds']); $this->uploadChunkTokenAndDeleteToken($token); if (empty($ret['etag'])) { return Response::generate(-1, 'MultiPartUpload completeMultipartUpload fail'); } $hashFileSize = 0; foreach ($token['partIds'] as $partId) { $hashFileSize += $partId['Size']; } if ($hashFileSize != $token['size']) { return Response::generate(-1, 'MultiPartUpload completeMultipartUpload fail (' . $hashFileSize . ',' . $token['size'] . ')'); } $dataTemp = $this->repository->addTemp($category, $token['path'], $token['name'], $token['size']); $data['data'] = $dataTemp; $data['path'] = $token['fullPath']; $data['finished'] = true; } } } return Response::generate(0, 'ok', $data); } public function updateDriverDomain($data) { $update = [ 'driver' => $this->option['driver'], 'domain' => $this->option['domain'], ]; $this->repository->updateData($data['id'], $update); return array_merge($data, $update); } public function getDriverFullPath($path) { $path = parent::getDriverFullPath($path); if (PathUtil::isPublicNetPath($path)) { return $path; } return $this->option['domain'] . $path; } }