123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- <?php
- namespace Api;
- use think\Config;
- use OSS\Model\RefererConfig;
- use service\SystemConfigService;
- use OSS\OssClient;
- use OSS\Core\OssException;
- use OSS\Core\OssUtil;
- /**
- * Class AliyunOss
- * @package Api
- */
- class AliyunOss extends AliyunSdk
- {
- /**
- * OSS存储桶名
- * @var string
- */
- protected $OssBucket;
- /**
- * OSS 地域节点
- * @var string
- */
- protected $OssEndpoint;
- /**
- * 外网访问地址
- * @var string
- */
- protected $uploadUrl;
- /**
- * 全局唯一的uploadId
- * @var string
- */
- protected $uploadId;
- /**
- * 正在上传的文件名
- * @var string
- */
- protected $object;
- /**
- * 上传验证规则
- * @var string
- */
- protected $autoValidate;
- /**
- * 是否开启防盗链
- * @var array
- */
- protected $referer;
- /**
- * 初始化参数
- */
- protected function _initialize()
- {
- $this->OssEndpoint = isset($this->config['OssEndpoint']) ? $this->config['OssEndpoint'] : null;
- $this->OssBucket = isset($this->config['OssBucket']) ? $this->config['OssBucket'] : null;
- $this->uploadUrl = isset($this->config['uploadUrl']) ? $this->config['uploadUrl'] : null;
- $this->checkUploadUrl();
- $this->referer = isset($this->config['referer']) && is_array($this->config['referer']) ? $this->config['referer'] : [];
- }
- /**
- * 验证合法上传域名
- */
- protected function checkUploadUrl()
- {
- $site_url=SystemConfigService::get('site_url');
- if($site_url){
- $arr = parse_url($site_url);
- if($arr['scheme']){
- $scheme=$arr['scheme'];
- }else{
- $scheme='http';
- }
- }else{
- $scheme='http';
- }
- if ($this->uploadUrl) {
- if ($scheme=='https') {
- if (strstr($this->uploadUrl, 'https') === false) {
- $this->uploadUrl = 'https://' . $this->uploadUrl;
- }
- }else{
- if (strstr($this->uploadUrl, 'http') === false) {
- $this->uploadUrl = 'http://' . $this->uploadUrl;
- }
- }
- }
- }
- /**
- * 初始化
- * @return null|\OSS\OssClient
- * @throws \OSS\Core\OssException
- */
- public function init()
- {
- if ($this->client === null) {
- $this->client = new OssClient($this->AccessKey, $this->AccessKeySecret, $this->OssEndpoint);
- if (!$this->client->doesBucketExist($this->OssBucket)) {
- $this->client->createBucket($this->OssBucket, OssClient::OSS_ACL_TYPE_PUBLIC_READ_WRITE);
- }
- if ($this->referer) {
- $refererConfig = new RefererConfig();
- // 设置允许空Referer。
- $refererConfig->setAllowEmptyReferer(true);
- foreach ($this->referer as $url) {
- $refererConfig->addReferer($url);
- }
- $this->client->putBucketReferer($this->OssBucket, $refererConfig);
- }
- }
- return $this->client;
- }
- /**
- * 设置防盗链
- * @param array $referer
- * @return $this
- */
- public function setReferer(array $referer = [])
- {
- $this->referer = $referer;
- return $this;
- }
- /**
- * 验证规则
- * @param array $autoValidate
- * @return $this
- */
- public function validate(array $autoValidate = [])
- {
- if (!$autoValidate) {
- $autoValidate = Config::get('upload.Validate');
- }
- $this->autoValidate = $autoValidate;
- return $this;
- }
- /**
- * 设置OSS存储桶名
- * @param string $OssBucket
- * @return $this
- * */
- public function setOssBucketAttr($OssBucket)
- {
- $this->OssBucket = $OssBucket;
- return $this;
- }
- /**
- * 设置OSS存储外网访问域名
- * @param string $OssEndpoint
- * @return $this
- * */
- public function setOssEndpointAttr($OssEndpoint)
- {
- $this->OssEndpoint = $OssEndpoint;
- return $this;
- }
- /**
- * 提取文件名
- * @param string $path
- * @param string $ext
- * @return string
- */
- protected function saveFileName($path = null, $ext = 'jpg')
- {
- return ($path ? substr(md5($path), 0, 5) : '') . date('YmdHis') . rand(0, 9999) . '.' . $ext;
- }
- /**
- * 获取文件后缀
- * @param \think\File $file
- * @return string
- */
- protected function getExtension(\think\File $file)
- {
- $pathinfo = pathinfo($file->getInfo('name'));
- return isset($pathinfo['extension']) ? $pathinfo['extension'] : '';
- }
- /**
- * 上传图片
- * @param $fileName
- * @return bool
- */
- public function upload($fileName)
- {
- $fileHandle = request()->file($fileName);
- $key = $this->saveFileName($fileHandle->getRealPath(), $this->getExtension($fileHandle));
- try {
- if ($this->autoValidate) {
- $fileHandle->validate($this->autoValidate);
- $this->autoValidate = null;
- }
- $uploadInfo = $this->init()->uploadFile($this->OssBucket, $key, $fileHandle->getRealPath());
- if (!isset($uploadInfo['info']['url'])) {
- return self::setErrorInfo('Upload failure');
- }
- return [
- 'url' => $uploadInfo['info']['url'],
- 'key' => $key
- ];
- } catch (\Throwable $e) {
- return self::setErrorInfo($e);
- }
- }
- /**文件分片上传
- * @param $fileName
- */
- public function sliceFileUpload($fileName)
- {
- $fileHandle = request()->file($fileName);
- $key = $this->saveFileName($fileHandle->getRealPath(), $this->getExtension($fileHandle));
- $this->object = $object = $key; //上传时生成的文件名
- $uploadFile = $fileHandle->getRealPath(); //文件真实路径
- /**
- * 步骤1:初始化一个分片上传事件,获取uploadId。
- */
- try{
- $ossClient = $this->init();
- //返回uploadId。uploadId是分片上传事件的唯一标识,您可以根据uploadId发起相关的操作,如取消分片上传、查询分片上传等。
- $this->uploadId = $uploadId = $ossClient->initiateMultipartUpload($this->OssBucket, $object);
- } catch(OssException $e) {
- return self::setErrorInfo($e->getMessage());
- }
- /*
- * 步骤2:上传分片。
- */
- $partSize = 10 * 1024 * 1024;
- $uploadFileSize = filesize($uploadFile);
- $pieces = $ossClient->generateMultiuploadParts($uploadFileSize, $partSize);
- $responseUploadPart = array();
- $uploadPosition = 0;
- $isCheckMd5 = true;
- foreach ($pieces as $i => $piece) {
- $fromPos = $uploadPosition + (integer)$piece[$ossClient::OSS_SEEK_TO];
- $toPos = (integer)$piece[$ossClient::OSS_LENGTH] + $fromPos - 1;
- $upOptions = array(
- // 上传文件。
- $ossClient::OSS_FILE_UPLOAD => $uploadFile,
- // 设置分片号。
- $ossClient::OSS_PART_NUM => ($i + 1),
- // 指定分片上传起始位置。
- $ossClient::OSS_SEEK_TO => $fromPos,
- // 指定文件长度。
- $ossClient::OSS_LENGTH => $toPos - $fromPos + 1,
- // 是否开启MD5校验,true为开启。
- $ossClient::OSS_CHECK_MD5 => $isCheckMd5,
- );
- // 开启MD5校验。
- if ($isCheckMd5) {
- $contentMd5 = OssUtil::getMd5SumForFile($uploadFile, $fromPos, $toPos);
- $upOptions[$ossClient::OSS_CONTENT_MD5] = $contentMd5;
- }
- try {
- // 上传分片。
- $responseUploadPart[] = $ossClient->uploadPart($this->OssBucket, $object, $uploadId, $upOptions);
- } catch(OssException $e) {
- return self::setErrorInfo($e->getMessage());
- }
- }
- // $uploadParts是由每个分片的ETag和分片号(PartNumber)组成的数组。
- $uploadParts = array();
- foreach ($responseUploadPart as $i => $eTag) {
- $uploadParts[] = array(
- 'PartNumber' => ($i + 1),
- 'ETag' => $eTag,
- );
- }
- /**
- * 步骤3:完成上传。
- */
- try {
- // 执行completeMultipartUpload操作时,需要提供所有有效的$uploadParts。OSS收到提交的$uploadParts后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
- $res=$ossClient->completeMultipartUpload($this->OssBucket, $object, $uploadId, $uploadParts);
- $this->object='';
- $this->uploadId='';
- } catch(OssException $e) {
- return self::setErrorInfo($e->getMessage());
- }
- $url=$res['info']['url'];
- $data=explode('?',$url);
- return [
- 'url' => $data[0],
- 'key' => $key
- ];
- }
- /**取消分片上传
- * @param $object 上传的文件名
- * @param $upload_id 上传时生成的上传ID
- * @return string
- */
- public function cancelFragmentUpload()
- {
- try{
- $ossClient = $this->init();
- $res=$ossClient->abortMultipartUpload($this->OssBucket, $this->object, $this->uploadId);
- } catch(OssException $e) {
- return $e->getMessage();
- }
- dump($res);exit;
- }
- /**
- * 文件流上传
- * @param string $fileContent
- * @param string|null $key
- * @return bool|mixed
- */
- public function stream(string $fileContent, string $key = null)
- {
- try {
- if (!$key) {
- $key = $this->saveFileName();
- }
- $uploadInfo = $this->init()->putObject($this->OssBucket, $key, $fileContent);
- if (!isset($uploadInfo['info']['url'])) {
- return self::setErrorInfo('Upload failure');
- }
- return [
- 'url' => $uploadInfo['info']['url'],
- 'key' => $key
- ];
- } catch (Throwable $e) {
- return self::setErrorInfo($e);
- }
- }
- /**
- * 删除指定资源
- * @param 资源key
- * @return array
- * */
- public function delOssFile($key)
- {
- try {
- return $this->init()->deleteObject($this->OssBucket, $key);
- } catch (\Exception $e) {
- return self::setErrorInfo($e);
- }
- }
- /**
- * 获取签名
- * @param string $callbackUrl
- * @param string $dir
- * @return string
- */
- public function getSignature($callbackUrl = '', $dir = '')
- {
- $base64CallbackBody = base64_encode(json_encode([
- 'callbackUrl' => $callbackUrl,
- 'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
- 'callbackBodyType' => "application/x-www-form-urlencoded"
- ]));
- $policy = json_encode([
- 'expiration' => $this->gmtIso8601(time() + 30),
- 'conditions' =>
- [
- [0 => 'content-length-range', 1 => 0, 2 => 1048576000],
- [0 => 'starts-with', 1 => '$key', 2 => $dir]
- ]
- ]);
- $base64Policy = base64_encode($policy);
- $signature = base64_encode(hash_hmac('sha1', $base64Policy, $this->AccessKeySecret, true));
- return [
- 'accessid' => $this->AccessKey,
- 'host' => $this->uploadUrl,
- 'policy' => $base64Policy,
- 'signature' => $signature,
- 'expire' => time() + 30,
- 'callback' => $base64CallbackBody
- ];
- }
- /**
- * 获取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 . "Z";
- }
- /**
- * 获取防盗链信息
- * @param string $bucket
- * @return RefererConfig
- * @throws \OSS\Core\OssException
- */
- public function getBucketReferer($bucket = '')
- {
- return $this->init()->getBucketReferer($bucket ? $bucket : $this->OssBucket);
- }
- /**
- * 清除防盗链
- * @param string $bucket
- * @return \OSS\Http\ResponseCore
- * @throws \OSS\Core\OssException
- */
- public function deleteBucketReferer($bucket = '')
- {
- $refererConfig = new RefererConfig();
- return $this->init()->putBucketReferer($bucket ? $bucket : $this->OssBucket, $refererConfig);
- }
- }
|