├── .gitignore ├── src ├── BadDiskException.php ├── UploadStrategyInterface.php ├── UploadException.php ├── UploadManagerServiceProvider.php ├── UploadStrategy.php ├── UploadValidator.php └── UploadManager.php ├── composer.json ├── database └── migrations │ ├── 2015_04_20_151900_create_uploads_table_zgldh.php │ └── 2015_11_18_132512_add_polymorphic_columns_to_uploads.php ├── config └── upload.php ├── model └── Upload.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.phar 2 | *.zip 3 | build/artifacts 4 | phpunit.xml 5 | phpunit.functional.xml 6 | .DS_Store 7 | .swp 8 | .build 9 | composer.lock 10 | vendor 11 | src/package.xml 12 | .idea/ 13 | -------------------------------------------------------------------------------- /src/BadDiskException.php: -------------------------------------------------------------------------------- 1 | errors = $errors; 18 | } 19 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zgldh/laravel-upload-manager", 3 | "license": "MIT", 4 | "description": "Upload, validate, storage, manage by API for Laravel 5/6/7/8/9", 5 | "keywords": [ 6 | "laravel", 7 | "upload", 8 | "validate", 9 | "storage", 10 | "manage", 11 | "api" 12 | ], 13 | "authors": [ 14 | { 15 | "name": "zgldh", 16 | "email": "zgldh@hotmail.com" 17 | } 18 | ], 19 | "require": { 20 | "laravel/framework": "^6.0|^7.0|^8.0|^9.0" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "zgldh\\UploadManager\\": "src/" 25 | } 26 | }, 27 | "extra": { 28 | "laravel": { 29 | "providers": [ 30 | "zgldh\\UploadManager\\UploadManagerServiceProvider" 31 | ] 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2015_04_20_151900_create_uploads_table_zgldh.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->nullable(); 19 | $table->string('description')->nullable(); 20 | $table->string('disk'); 21 | $table->string('path'); 22 | $table->integer('size'); 23 | $table->integer('user_id')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('uploads'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /config/upload.php: -------------------------------------------------------------------------------- 1 | 'local', 15 | 16 | /** 17 | * 对应的数据模型类 18 | **/ 19 | 'upload_model' => App\Upload::class, 20 | 21 | /** 22 | * 上传策略类 23 | **/ 24 | 'upload_strategy' => zgldh\UploadManager\UploadStrategy::class, 25 | 26 | /** 27 | * validator group 用于 withValidator()函数 common是默认的。 28 | **/ 29 | 'validator_groups' => [ 30 | 'common' => [ 31 | /** 32 | * 请参考 http://laravel.com/docs/5.1/validation 33 | **/ 34 | 'min' => 0, //kilobytes 35 | 'max' => 4096, //kilobytes 36 | ], 37 | 'image' => [ 38 | 'max' => 8192, //kilobytes 39 | 'mimes' => 'jpeg,bmp,png,gif' 40 | ] 41 | ], 42 | 43 | /** 44 | * 已上传,但未使用的文件的过期时长。单位是秒 45 | * 设置为 -1 则不会删除未使用的文件。 46 | * 如果一个 Upload 对象没有 uploadable 关联对象, 则该 Upload 对象未使用。 47 | */ 48 | 'unused_lifetime' => -1 49 | ]; -------------------------------------------------------------------------------- /database/migrations/2015_11_18_132512_add_polymorphic_columns_to_uploads.php: -------------------------------------------------------------------------------- 1 | integer('uploadable_id')->nullable(); 17 | $table->string('uploadable_type')->nullable(); 18 | 19 | $table->index([ 20 | 'uploadable_id', 21 | 'uploadable_type' 22 | ],'uploadable_index'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::table('uploads', function (Blueprint $table) { 34 | $table->dropIndex('uploadable_index'); 35 | }); 36 | Schema::table('uploads', function (Blueprint $table) { 37 | $table->dropColumn('uploadable_id'); 38 | $table->dropColumn('uploadable_type'); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/UploadManagerServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton('zgldh\UploadManager\UploadStrategyInterface', \Config::get('upload.upload_strategy')); 24 | $this->app->singleton('upload-manager', 'zgldh\UploadManager\UploadManager'); 25 | 26 | $this->mergeConfigFrom( 27 | __DIR__ . '/../config/upload.php', 'upload' 28 | ); 29 | } 30 | 31 | public function boot() 32 | { 33 | $this->publishes([ 34 | __DIR__ . '/../config/upload.php' => config_path('upload.php'), 35 | __DIR__ . '/../database/migrations/' => database_path('/migrations'), 36 | __DIR__ . '/../model/Upload.php' => app_path('Upload.php') 37 | ]); 38 | 39 | $modelClassName = config('upload.upload_model'); 40 | if (class_exists($modelClassName)) { 41 | $modelClassName::deleted( 42 | function ($upload) { 43 | // 44 | $upload->deleteFile(false); 45 | } 46 | ); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/UploadStrategy.php: -------------------------------------------------------------------------------- 1 | getRealPath()) . time()) . '.' . $file->getClientOriginalExtension(); 23 | } elseif (is_a($file, SplFileInfo::class)) { 24 | $filename = date('Y-m-d-') . md5(md5_file($file->getRealPath()) . time()) . '.' . $file->getExtension(); 25 | } elseif (is_string($file)) { 26 | $extension = \File::extension($file); 27 | $filename = date('Y-m-d-') . md5($file . time()) . '.' . $extension; 28 | } else { 29 | throw new \RuntimeException(__METHOD__ . ' needs a UploadedFile|SplFileInfo|string instance or a file path string'); 30 | } 31 | return $filename; 32 | } 33 | 34 | /** 35 | * 生成储存的相对路径 36 | * @param $filename 37 | * @return string 38 | */ 39 | public function makeStorePath($filename) 40 | { 41 | $path = 'uploads/' . $filename; 42 | return $path; 43 | } 44 | } -------------------------------------------------------------------------------- /model/Upload.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\User', 'user_id', 'id'); 23 | } 24 | 25 | public function uploadable() 26 | { 27 | return $this->morphTo(); 28 | } 29 | 30 | public function scopeUsed($query) 31 | { 32 | return $query->has('uploadable'); 33 | } 34 | 35 | public function scopeUnUsed($query) 36 | { 37 | return $query->whereNull('uploadable_id')->whereNull('uploadable_type'); 38 | } 39 | 40 | public function getUrlAttribute() 41 | { 42 | $manager = UploadManager::getInstance(); 43 | $url = $manager->getUploadUrl($this->disk, $this->path); 44 | return $url; 45 | } 46 | 47 | public function deleteFile($autoSave = true) 48 | { 49 | if ($this->path) { 50 | $disk = \Storage::disk($this->disk); 51 | if ($disk->exists($this->path)) { 52 | $disk->delete($this->path); 53 | $this->path = ''; 54 | if ($autoSave) { 55 | $this->save(); 56 | } 57 | } 58 | } 59 | } 60 | 61 | public function isInDisk($diskName) 62 | { 63 | return $this->disk == $diskName ? true : false; 64 | } 65 | 66 | public function moveToDisk($newDiskName) 67 | { 68 | if ($newDiskName == $this->disk) { 69 | return true; 70 | } 71 | $currentDisk = \Storage::disk($this->disk); 72 | $content = $currentDisk->get($this->path); 73 | 74 | $newDisk = \Storage::disk($newDiskName); 75 | $newDisk->put($this->path, $content); 76 | if ($newDisk->exists($this->path)) { 77 | $this->disk = $newDiskName; 78 | $this->save(); 79 | $currentDisk->delete($this->path); 80 | return true; 81 | } 82 | return false; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/UploadValidator.php: -------------------------------------------------------------------------------- 1 | $tempFile]; 29 | $rules = ['upload' => $rules]; 30 | 31 | $messages = [ 32 | 'upload.min' => trans('validation.min.file'), 33 | 'upload.max' => trans('validation.max.file'), 34 | 'upload.size' => trans('validation.size.file'), 35 | 'upload.between' => trans('validation.between.file') 36 | ]; 37 | $validator = \Validator::make($data, $rules, $messages); 38 | 39 | if ($validator->fails()) { 40 | self::removeTempFile(); 41 | $messages = $validator->errors(); 42 | $errors = $messages->get('upload'); 43 | throw new UploadException($errors); 44 | } 45 | self::removeTempFile(); 46 | return true; 47 | } 48 | 49 | private static function mergeValidators($validatorGroups) 50 | { 51 | $validators = []; 52 | if (is_array($validatorGroups)) { 53 | foreach ($validatorGroups as $validatorGroup) { 54 | $groupItems = config('upload.validator_groups.' . $validatorGroup); 55 | $validators = $validators + $groupItems; 56 | } 57 | } 58 | $validators = $validators + config('upload.validator_groups.common'); 59 | 60 | return $validators; 61 | } 62 | 63 | private static function makeRules($validators) 64 | { 65 | $rules = []; 66 | foreach ($validators as $key => $value) { 67 | if ($key == null) { 68 | continue; 69 | } 70 | if ($value === null) { 71 | $rule = $key; 72 | } else { 73 | $rule = $key . ':' . $value; 74 | } 75 | $rules[] = $rule; 76 | } 77 | $rules = join('|', $rules); 78 | return $rules; 79 | } 80 | 81 | private static $tempFileName = null; 82 | 83 | private static function getTempFileName($fileContent = null) 84 | { 85 | if (self::$tempFileName == null) { 86 | self::$tempFileName = time() . md5($fileContent); 87 | } 88 | return self::$tempFileName; 89 | } 90 | 91 | private static function storeTempFile($fileContent) 92 | { 93 | $filename = self::getTempFileName($fileContent); 94 | $filePath = storage_path('framework' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . $filename); 95 | file_put_contents($filePath, $fileContent); 96 | $file = new File($filePath); 97 | return $file; 98 | } 99 | 100 | private static function removeTempFile() 101 | { 102 | if (self::$tempFileName) { 103 | $filePath = storage_path('framework' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . self::$tempFileName); 104 | unlink($filePath); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-upload-manager 2 | 通过API对文件进行“上传、验证、储存、管理”操作。 3 | Upload, validate, storage, manage by API for Laravel 5/6/7/8/9 4 | 5 | ## 依赖 Requirement 6 | 7 | 1. Laravel >= 6.0 8 | 9 | 2. For Laravel 5, Please use `composer require zgldh/laravel-upload-manager 0.6` 10 | 11 | ## 安装 Install 12 | 13 | 1. composer require zgldh/laravel-upload-manager 14 | 2. ```config/app.php``` ```'providers' => [ 'zgldh\UploadManager\UploadManagerServiceProvider']``` 15 | 3. php artisan vendor:publish --provider="zgldh\UploadManager\UploadManagerServiceProvider" 16 | 4. php artisan migrate 17 | 5. Done 18 | 19 | ## 用法 Usage 20 | 21 | 1. 上传一个文件 Upload and store a file. 22 | 23 | ```php 24 | 25 | use zgldh\UploadManager\UploadManager; 26 | 27 | class UploadController extend Controller 28 | { 29 | public function postUpload(Request $request) 30 | { 31 | $file = $request->file('avatar'); 32 | $manager = UploadManager::getInstance(); 33 | $upload = $manager->upload($file); 34 | $upload->save(); 35 | return $upload; 36 | } 37 | } 38 | ``` 39 | 40 | 2. 从一个URL获取并保存文件 Fetch and store a file from a URL 41 | 42 | ```php 43 | 44 | use zgldh\UploadManager\UploadManager; 45 | 46 | class UploadController extend Controller 47 | { 48 | public function postUpload(Request $request) 49 | { 50 | $fileUrl = $request->input('url'); 51 | $manager = UploadManager::getInstance(); 52 | $upload = $manager->upload($fileUrl); 53 | $upload->save(); 54 | return $upload; 55 | } 56 | } 57 | ``` 58 | 59 | 3. 更新一个上传对象 Update a upload object 60 | 61 | ```php 62 | 63 | use App\Upload; 64 | use zgldh\UploadManager\UploadManager; 65 | 66 | class UploadController extend Controller 67 | { 68 | public function postUpload(Request $request) 69 | { 70 | $uploadId = $request->input('id'); 71 | $file = $request->file('avatar'); 72 | 73 | $manager = UploadManager::getInstance(); 74 | $upload = Upload::find($uploadId); 75 | if($manager->update($upload, $file)) 76 | { 77 | $upload->save(); 78 | return $upload; 79 | } 80 | return ['result'=>false]; 81 | } 82 | } 83 | ``` 84 | 85 | 4. 用从一个URL获取到的文件来更新一个上传对象 Update a upload object from a URL 86 | 87 | ```php 88 | 89 | use App\Upload; 90 | use zgldh\UploadManager\UploadManager; 91 | 92 | class UploadController extend Controller 93 | { 94 | public function postUpload(Request $request) 95 | { 96 | $uploadId = $request->input('id'); 97 | $fileUrl = $request->input('url'); 98 | 99 | $manager = UploadManager::getInstance(); 100 | $upload = Upload::find($uploadId); 101 | if($manager->update($upload, $fileUrl)) 102 | { 103 | $upload->save(); 104 | return $upload; 105 | } 106 | return ['result'=>false]; 107 | } 108 | } 109 | ``` 110 | 111 | 5. 数据验证 Validation 112 | 113 | ```php 114 | 115 | use zgldh\UploadManager\UploadManager; 116 | 117 | class UploadController extend Controller 118 | { 119 | public function postUpload(Request $request) 120 | { 121 | $file = $request->file('avatar'); 122 | $manager = UploadManager::getInstance(); 123 | $upload = $manager->withValidator('image')->upload($file); //加上验证组 124 | 125 | if($upload) 126 | { 127 | $upload->save(); 128 | return $upload; 129 | } 130 | else 131 | { 132 | $errorMessages = $manager->getErrors(); //得到所有错误信息 133 | $errorMessage = $manager->getFirstErrorMessage(); //得到第一条错误信息 134 | throw new \Exception($errorMessage); 135 | } 136 | } 137 | } 138 | ``` 139 | 140 | 6. 存到别的Disk里面 141 | 142 | ```php 143 | 144 | use zgldh\UploadManager\UploadManager; 145 | 146 | class UploadController extend Controller 147 | { 148 | public function postUpload(Request $request) 149 | { 150 | $file = $request->file('avatar'); 151 | $manager = UploadManager::getInstance(); 152 | $upload = $manager 153 | ->withValidator('image') 154 | ->withDisk('qiniu') // 储存到七牛磁盘里 155 | ->upload($file); 156 | $upload->save(); 157 | return $upload; 158 | } 159 | } 160 | ``` 161 | 162 | 7. 上传前修改``` $upload ``` 对象 163 | 164 | ```php 165 | 166 | use zgldh\UploadManager\UploadManager; 167 | 168 | class UploadController extend Controller 169 | { 170 | public function postUpload(Request $request) 171 | { 172 | $file = $request->file('avatar'); 173 | $manager = UploadManager::getInstance(); 174 | $upload = $manager 175 | ->withValidator('image') 176 | ->withDisk('localhost') // 默认存到本地 177 | ->upload($file, function($upload){ 178 | if($upload->size > 1024*1024) 179 | { 180 | $upload->disk = 'qiniu';// 超过1兆的文件都放到七牛里。 181 | } 182 | return $upload; 183 | }); 184 | $upload->save(); 185 | return $upload; 186 | } 187 | } 188 | ``` 189 | 190 | 8. 删除某用户上传后,却一直没有使用的`avatar`类型的``` $upload ``` 对象 191 | 192 | ```php 193 | 194 | use zgldh\UploadManager\UploadManager; 195 | 196 | class UploadController extend Controller 197 | { 198 | public function clearUnUsed(Request $request) 199 | { 200 | $currentUser = $request->user(); 201 | $manager = UploadManager::getInstance(); 202 | $manager->removeUnUsedUploads($currentUser, 'avatar'); 203 | } 204 | } 205 | ``` 206 | 207 | ## 配置 Configuration 208 | 209 | 1. ``` config/upload.php ``` 210 | 211 | 请查看源文件注释 212 | 213 | 2. ``` App\Upload ``` 214 | 215 | 可以在里面写自己喜欢的函数 216 | 217 | 3. ``` UploadStrategy.php ``` 218 | 219 | 通常需要你亲自扩展一个出来。如: 220 | 221 | ```php 222 | 223 | strategy = self::getStrategy(); 38 | $this->withDisk(); 39 | } 40 | 41 | /** 42 | * @return UploadManager 43 | */ 44 | public static function getInstance() 45 | { 46 | return \App::make('upload-manager'); 47 | } 48 | 49 | /** 50 | * @return UploadStrategyInterface 51 | */ 52 | public static function getStrategy() 53 | { 54 | return \App::make('zgldh\UploadManager\UploadStrategyInterface'); 55 | } 56 | 57 | /** 58 | * 得到已上传文件的URL 59 | * @param $disk 60 | * @param $path 61 | * @return string 62 | */ 63 | public function getUploadUrl($disk, $path) 64 | { 65 | $url = ''; 66 | $methodName = 'get' . ucfirst(Str::camel($disk)) . 'Url'; 67 | if (method_exists($this->strategy, $methodName)) { 68 | $url = $this->strategy->$methodName($path); 69 | } 70 | return $url; 71 | } 72 | 73 | /** 74 | * 设置默认disk名字 75 | * @param $diskName config/filesystems.php disks数组内的key 76 | * @return $this 77 | * @throws \Exception 78 | */ 79 | public function withDisk($diskName = null) 80 | { 81 | if ($diskName == null) { 82 | $this->diskName = \Config::get('upload.base_storage_disk'); 83 | } elseif (\Config::has('filesystems.disks.' . $diskName)) { 84 | $this->diskName = $diskName; 85 | } else { 86 | throw new BadDiskException("Bad disk name: " . $diskName); 87 | } 88 | return $this; 89 | } 90 | 91 | /** 92 | * 设置验证机制, 要在upload、update之前调用 93 | * @param $validatorGroups 验证组的名字 94 | * @return $this 95 | */ 96 | public function withValidator($validatorGroups) 97 | { 98 | if (!is_array($validatorGroups)) { 99 | $validatorGroups = [$validatorGroups]; 100 | } 101 | $this->validatorGroups = $validatorGroups; 102 | return $this; 103 | } 104 | 105 | /** 106 | * 核心上传 107 | * @param $upload Upload object 108 | * @param $uploadedFilePath string (path) 109 | * @param $file UploadedFile / string 110 | * @param $preCallback function 111 | * @return bool 112 | */ 113 | private function coreUpload($upload, $uploadedFilePath, $file, $preCallback) 114 | { 115 | try { 116 | $newName = $this->strategy->makeFileName($file); 117 | $path = $this->strategy->makeStorePath($newName); 118 | 119 | $content = file_get_contents($uploadedFilePath); 120 | UploadValidator::validate($content, $this->validatorGroups); 121 | 122 | $upload->path = $path; 123 | $upload->disk = $this->diskName; 124 | $upload->size = strlen($content); 125 | 126 | if (is_callable($preCallback)) { 127 | $upload = $preCallback($upload); 128 | } 129 | if (!$upload) { 130 | unset($content); 131 | return false; 132 | } 133 | 134 | $disk = \Storage::disk($upload->disk); 135 | if ($disk->put($upload->path, $content) == false) { 136 | return false; 137 | } 138 | } catch (UploadException $e) { 139 | $this->storeErrors($e); 140 | return false; 141 | } 142 | return $upload; 143 | } 144 | 145 | private function newUploadModel() 146 | { 147 | $modelClassName = config('upload.upload_model'); 148 | $model = app($modelClassName); 149 | return $model; 150 | } 151 | 152 | /** 153 | * 保存上传文件,生成上传对象 154 | * @param $file 155 | * @param null $preCallback 156 | * @return Upload|bool 157 | */ 158 | public function upload($file, $preCallback = null) 159 | { 160 | if (is_string($file)) { 161 | return $this->uploadByUrl($file, $preCallback); 162 | } 163 | 164 | $upload = $this->newUploadModel(); 165 | $upload->disk = $this->diskName; 166 | 167 | $uploadedFilePath = $file->getPathname(); 168 | $upload = $this->coreUpload($upload, $uploadedFilePath, $file, $preCallback); 169 | 170 | return $upload; 171 | } 172 | 173 | /** 174 | * 从URL获取文件并保存,生成上传对象 175 | * @param $url 176 | * @param null $preCallback 177 | * @return Upload|bool 178 | */ 179 | public function uploadByUrl($url, $preCallback = null) 180 | { 181 | $upload = $this->newUploadModel(); 182 | $upload->disk = $this->diskName; 183 | 184 | $uploadedFilePath = $url; 185 | $upload = $this->coreUpload($upload, $uploadedFilePath, $url, $preCallback); 186 | 187 | return $upload; 188 | } 189 | 190 | /** 191 | * 用已上传文件更新一个上传对象 192 | * @param $upload 193 | * @param UploadedFile $file 194 | * @param null $preCallback 195 | * @return bool 196 | */ 197 | public function update(&$upload, $file, $preCallback = null) 198 | { 199 | if (is_string($file)) { 200 | return $this->updateByUrl($upload, $file, $preCallback); 201 | } 202 | $oldDisk = $upload->disk; 203 | $oldPath = $upload->path; 204 | 205 | $uploadedFilePath = $file->getPathname(); 206 | $result = $this->coreUpload($upload, $uploadedFilePath, $file, $preCallback); 207 | if ($result) { 208 | $this->removeOldFile($oldDisk, $oldPath); 209 | $upload = $result; 210 | } else { 211 | $upload->disk = $oldDisk; 212 | $upload->path = $oldPath; 213 | return false; 214 | } 215 | return true; 216 | } 217 | 218 | /** 219 | * 用URL更新一个上传对象 220 | * @param $upload 221 | * @param $url 222 | * @param null $preCallback 223 | * @return bool 224 | */ 225 | public function updateByUrl(&$upload, $url, $preCallback = null) 226 | { 227 | $oldDisk = $upload->disk; 228 | $oldPath = $upload->path; 229 | 230 | $uploadedFilePath = $url; 231 | $result = $this->coreUpload($upload, $uploadedFilePath, $url, $preCallback); 232 | if ($result) { 233 | $this->removeOldFile($oldDisk, $oldPath); 234 | $upload = $result; 235 | } else { 236 | $upload->disk = $oldDisk; 237 | $upload->path = $oldPath; 238 | return false; 239 | } 240 | 241 | return true; 242 | } 243 | 244 | private function removeOldFile($disk, $path) 245 | { 246 | if ($disk && $path) { 247 | $disk = \Storage::disk($disk); 248 | if ($disk) { 249 | $disk->delete($path); 250 | } 251 | } 252 | } 253 | 254 | public function storeErrors(UploadException $e) 255 | { 256 | \Log::error($e); 257 | $this->errors = $e->errors; 258 | //TODO 259 | } 260 | 261 | /** 262 | * @return null 263 | */ 264 | public function getErrors() 265 | { 266 | return $this->errors; 267 | } 268 | 269 | /** 270 | * 得到第一个错误信息 271 | * @return mixed 272 | */ 273 | public function getFirstErrorMessage() 274 | { 275 | if (isset($this->errors[0])) { 276 | reset($this->errors); 277 | $error = each($this->errors); 278 | reset($this->errors); 279 | return $error['value']; 280 | } 281 | } 282 | 283 | /** 284 | * 删除未使用的上传对象。 285 | * @param int $userId 上传者ID 286 | * @param string $type 上传类型 287 | */ 288 | public function removeUnUsedUploads($userId = null, $type = null) 289 | { 290 | $unusedLifetime = config('upload.unused_lifetime', -1); 291 | if ($unusedLifetime === -1) { 292 | return; 293 | } 294 | $upload = $this->newUploadModel(); 295 | $upload = $upload->unUsed(); 296 | $expiredTime = date('Y-m-d H:i:s', time() - $unusedLifetime); 297 | $upload = $upload->where('created_at', '<', $expiredTime); 298 | if ($userId) { 299 | $upload = $upload->where('user_id', $userId); 300 | } 301 | if ($type) { 302 | $upload = $upload->where('type', $type); 303 | } 304 | return $upload->delete(); 305 | } 306 | } 307 | --------------------------------------------------------------------------------