<?php namespace Meibuyu\Common\UploadOss; use Hyperf\Contract\ConfigInterface; use League\Flysystem\Filesystem; use Hyperf\Filesystem\FilesystemFactory; use Hyperf\HttpMessage\Upload\UploadedFile; use League\Flysystem\FileExistsException; use Meibuyu\Common\Exceptions\HttpResponseException; use Psr\Container\ContainerInterface; class UploadOssService { /** * @var FilesystemFactory */ private $factory; /** * @var ConfigInterface */ private $config; /** * @var string */ private $urlPrefix; /** * @var string */ private $appDev; /** * @var string */ private $appName; /** * 是否自动保存数据库 * @var bool */ private $autoSaveDataBase = true; public static $options = [ 'maxSize' => 10 * 1024 * 1024, // 文件大小,10M 'mime' => ['jpeg', 'png', 'gif', 'jpg', 'svg', 'txt', 'pdf', 'xlsx', 'xls', 'doc', 'docx', 'rar', 'zip', 'csv'], // 允许上传的文件类型 ]; public function __construct(ContainerInterface $container) { $this->config = $container->get(ConfigInterface::class); $this->factory = $container->get(FilesystemFactory::class); $ossConfig = $this->config->get('file.storage.oss'); $this->urlPrefix = 'https://' . $ossConfig['bucket'] . '.' . $ossConfig['endpoint'] . '/'; $this->appDev = $this->config->get('app_env'); $this->appName = $this->config->get('app_name'); } /** * 设置是否自动保存记录到数据库 * @param bool $bool * @author chentianyu */ public function setAutoSaveDataBase(bool $bool) { $this->autoSaveDataBase = $bool; } /** * 上传图片 * @param \Hyperf\HttpMessage\Upload\UploadedFile $image * @param string $module * @return array|string * @throws \Meibuyu\Common\Exceptions\HttpResponseException * @author chentianyu */ public function uploadImage(UploadedFile $image, string $module, $userId, $uniqueFileName = true) { $ext = $image->getExtension(); $clientFilename = $image->getClientFilename(); $fileName = $uniqueFileName ? ($this->genUniqueFileName() . '.' . $ext) : $clientFilename; $options = ['mime' => ['jpeg', 'png', 'gif', 'jpg', 'svg']]; $filePath = 'oss2/' . $this->appDev . "/" . $this->appName . "/$module/images/" . today() . "/$userId/" . $fileName; $this->upload($image, $filePath, $options); if($this->autoSaveDataBase){ $model = new FileModel(); $model = $model->newInstance([ 'type' => 'image', 'module' => $module, 'user_id' => $userId, 'source_name' => $clientFilename, 'name' => $fileName, 'path' => $this->urlPrefix . $filePath, 'ext' => $ext, 'size' => num_2_file_size($image->getSize()), ]); $model->save(); return $model->toArray(); }else{ return $this->urlPrefix . $filePath; } } /** * 上传文件 * @param \Hyperf\HttpMessage\Upload\UploadedFile $image * @param string $module * @return array|string * @throws \Meibuyu\Common\Exceptions\HttpResponseException * @author chentianyu */ public function uploadFile(UploadedFile $file, string $module, $userId, $uniqueFileName = true, array $options = []) { $ext = $file->getExtension(); $clientFilename = $file->getClientFilename(); $fileName = $uniqueFileName ? ($this->genUniqueFileName() . '.' . $ext) : $clientFilename; $filePath = 'oss2/' . $this->appDev . "/" . $this->appName . "/$module/files/" . today() . "/$userId/" . $fileName; $this->upload($file, $filePath, $options); if($this->autoSaveDataBase){ $model = new FileModel(); $model = $model->newInstance([ 'type' => 'file', 'module' => $module, 'user_id' => $userId, 'source_name' => $clientFilename, 'name' => $fileName, 'path' => $this->urlPrefix . $filePath, 'ext' => $ext, 'size' => num_2_file_size($file->getSize()), ]); $model->save(); return $model->toArray(); }else{ return $this->urlPrefix . $filePath; } } /** * @param \Hyperf\HttpMessage\Upload\UploadedFile $file * @param $filePath * @param array $options * @return bool * @throws \Meibuyu\Common\Exceptions\HttpResponseException * @author chentianyu */ public function upload(UploadedFile $file, string $filePath, array $options = []) { if ($file->isValid()) { $options = array_merge(self::$options, $options); $extension = strtolower($file->getExtension()); // 通过扩展名判断类型 if (!in_array($extension, $options['mime'])) { throw new HttpResponseException('文件类型不支持,目前只支持' . implode(',', $options['mime'])); } // 判断文件大小 if ($file->getSize() > $options['maxSize']) { throw new HttpResponseException('文件超出系统规定的大小,最大不能超过' . num_2_file_size($options['maxSize'])); } try { $oss = $this->factory->get('oss'); $stream = fopen($file->getRealPath(), 'r+'); $res = $oss->writeStream($filePath, $stream); is_resource($stream) && fclose($stream); return $res; } catch (FileExistsException $e) { throw new HttpResponseException($e->getMessage()); } } else { throw new HttpResponseException('文件无效'); } } /** * 上传本地文件到oss * @param string $localFilePath * @param string $ossFilePath 枚举key * @param bool $fixedDir 使用oss固定目录 * @return mixed * @throws HttpResponseException * @author Liu lu * date 2023-02-09 */ public function uploadLocalFile(string $localFilePath, string $ossFilePath,$fixedDir=false) { $extension = pathinfo(parse_url($localFilePath,PHP_URL_PATH),PATHINFO_EXTENSION); if($fixedDir){ $ossFilePath = 'oss2/'.env('APP_ENV').'/'.env('APP_NAME') ."/{$ossFilePath}/". md5($localFilePath).'.'.$extension; }else{ $fileName = $this->genUniqueFileName() . '.' . $extension; $ossFilePath = 'oss2/'. $this->appDev .'/'. $this->appName ."/{$ossFilePath}/". today() .'/'. $fileName; } try { $oss = $this->factory->get('oss'); $stream = fopen($localFilePath, 'r+'); $oss->writeStream($ossFilePath, $stream); is_resource($stream) && fclose($stream); return $this->urlPrefix . $ossFilePath; } catch (FileExistsException $e) { throw new HttpResponseException($e->getMessage()); } } /** * 生成唯一文件名 * @return string * @author chentianyu */ public function genUniqueFileName() { return date('YmdHis') . uniqid(); } }