accessKey = $config['accessKey'] ?? null; $this->secretKey = $config['secretKey'] ?? null; $this->uploadUrl = tidy_url($this->checkUploadUrl($config['uploadUrl'] ?? '')); $this->storageName = $config['storageName'] ?? null; $this->storageRegion = $config['storageRegion'] ?? null; $this->cdn = $config['cdn'] ?? null; $this->thumb_status = $config['thumb_status']; $this->thumb_rate = $config['thumb_rate']; $this->upload_max_size = $config['upload_max_size']; } /** * 初始化oss * @return OssClient * @throws OssException */ protected function app() { if (!$this->accessKey || !$this->secretKey) { throw new UploadException('Please configure accessKey and secretKey'); } $this->handle = new S3Client([ 'endpoint' => $this->uploadUrl, 'accessKeyId' => $this->accessKey, 'accessKeySecret' => $this->secretKey, 'region' => $this->storageRegion, ]); return $this->handle; } /** * 上传文件 * @param string $file * @return array|bool|mixed|\StdClass */ public function move(string $file = 'file',$thumb = true) { $fileHandle = app()->request->file($file); if ($this->upload_max_size && $fileHandle->getSize() < $this->upload_max_size) $this->thumb_status = false; if (!$fileHandle) { return $this->setError('Upload file does not exist'); } if ($this->validate) { try { validate([$file => $this->validate])->check([$file => $fileHandle]); } catch (ValidateException $e) { return $this->setError($e->getMessage()); } } $key = $this->saveFileName($fileHandle->getRealPath(), $fileHandle->getOriginalExtension()); $path = ($this->path ? trim($this->path , '/') . '/' : ''); try { $uploadInfo = $this->app()->PutObject([ 'Bucket' => $this->storageName, 'Key' => $path.$key, 'Body' => fopen($fileHandle,'r'), ]); if ($uploadInfo->info()['response']->getStatusCode() == 200) { if($this->cdn) { $src =rtrim($this->cdn).$path.$key; } else { $src = $uploadInfo->info()['response']->getInfo()['url']; } } if ($thumb) $src = $this->thumb($src); $this->fileInfo->uploadInfo = $uploadInfo; $this->fileInfo->filePath = $src; $this->fileInfo->fileName = $key; return $this->fileInfo; } catch (UploadException $e) { return $this->setError($e->getMessage()); } } /** * 文件流上传 * @param string $fileContent * @param string|null $key * @return bool|mixed */ public function stream(string $fileContent, string $key = null, $thumb = true) { try { if (!$key) { $key = $this->saveFileName(); } $path = ($this->path ? trim($this->path , '/') . '/' : ''); $fileContent = (string)EntityBody::factory($fileContent); $uploadInfo = $this->app()->PutObject([ 'Bucket' => $this->storageName, 'Key' => $path.$key, 'Body' => $fileContent, ]); if ($uploadInfo->info()['response']->getStatusCode() == 200) { if($this->cdn) { $src =rtrim($this->cdn).$path.$key; } else { $src = $uploadInfo->info()['response']->getInfo()['url']; } } if ($thumb) $src = $this->thumb($src); $this->fileInfo->uploadInfo = $uploadInfo; $this->fileInfo->filePath = $src; $this->fileInfo->fileName = $key; return $this->fileInfo; } catch (UploadException $e) { return $this->setError($e->getMessage()); } } /** * 缩略图 * @param string $filePath * @param string $type * @return mixed|string[] */ public function thumb(string $key = '') { $suffix = explode('.',$key); if (!$suffix && !in_array($suffix[1],config('upload.iamge_fileExt'))) return $key; if ($this->thumb_status && $key) { $param = ('x-oss-process=img/sp'. $this->thumb_rate); $key = $key . '?' . $param; } return $key; } /** * 删除资源 * @param $key * @return mixed */ public function delete(string $key) { try { return $this->app()->deleteObject([ 'Bucket' => $this->storageName, 'Key' => $key, ]); } catch (Exception $e) { return $this->setError($e->getMessage()); } } public function buildSigningKey(array $credentialScope): string { $signingKey = 'AWS4' . $this->accessKey; foreach ($credentialScope as $scopePart) { $signingKey = hash_hmac('sha256', $scopePart, $signingKey, true); } return $signingKey; } public function buildStringToSign(\DateTimeImmutable $now, string $credentialString, string $canonicalRequest): string { return implode("\n", [ 'AWS4-HMAC-SHA256', $now->format('Ymd\THis\Z'), $credentialString, hash('sha256', $canonicalRequest), ]); } /** * 获取OSS上传密钥 * @return mixed|void */ public function getTempKeys($callbackUrl = '', $dir = '') { $ldt = gmdate('Ymd\THis\Z'); $sdt = substr($ldt, 0, 8); $key = $this->getSigningKey( $sdt, $this->storageRegion, 's3', $this->accessKey ); $credential = [$sdt, $this->storageRegion, 's3', 'aws4_request']; $policy = json_encode([ 'expiration' => gmdate('Y-m-d\TH:i:s\Z', time()), 'conditions' => [ ['bucket' => $this->storageRegion], ['success_action_status' => 200], ['X-Amz-Credential' => $this->accessKey.'/'.implode('/', $credential)], ['X-Amz-Algorithm' => 'AWS4-HMAC-SHA256'], ['X-Amz-Date' => $ldt] ] ]); $jsonPolicy64 = base64_encode($policy); $signature = bin2hex(hash_hmac('sha256', $jsonPolicy64, $key, true)); return [ 'expiration' => $ldt, 'storageName' => $this->storageName, 'storageRegion' => $this->storageRegion, 'signature' => $signature, 'credential' => $this->accessKey.'/'.implode('/', $credential), 'policy'=> $jsonPolicy64, 'type' => 'JDOSS', 'cdn' => $this->cdn, ]; } public function getSigningKey($shortDate, $region, $service, $secretKey) { $kSecret = 'AWS4' . $secretKey; $kDate = hash_hmac('sha256', $shortDate, $kSecret, true); $kRegion = hash_hmac('sha256', $region, $kDate, true); $kService = hash_hmac('sha256', $service, $kRegion, true); return hash_hmac('sha256', 'aws4_request', $kService, true); } /** * 获取ISO时间格式 * @param $time * @return string */ protected function gmtIso8601($time) { $dtStr = date("c", $time); $mydatetime = new \DateTime($dtStr); $expiration = $mydatetime->format(\DateTime::ISO8601); $pos = strpos($expiration, '+'); $expiration = substr($expiration, 0, $pos); return $expiration . ".000Z"; } }