From d0b7c84bbaa3b6106571eb9383fe1c88e7181fae Mon Sep 17 00:00:00 2001 From: Chenx221 Date: Sun, 10 Mar 2024 13:20:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=89=A9=E4=BD=99=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E7=9A=84=E5=88=A4=E6=96=AD=20*=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E6=B2=A1=E6=9C=89bug=E4=BA=86=E5=90=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/CollectionController.php | 10 +++- controllers/HomeController.php | 86 +++++++++++++++++++--------- models/UploadForm.php | 8 ++- utils/FileSizeHelper.php | 29 +++++++++- 4 files changed, 102 insertions(+), 31 deletions(-) diff --git a/controllers/CollectionController.php b/controllers/CollectionController.php index 57911f4..40b6a21 100644 --- a/controllers/CollectionController.php +++ b/controllers/CollectionController.php @@ -5,6 +5,7 @@ namespace app\controllers; use app\models\CollectionTasks; use app\models\CollectionSearch; use app\models\CollectionUploaded; +use app\utils\FileSizeHelper; use Ramsey\Uuid\Uuid; use RuntimeException; use Yii; @@ -52,8 +53,8 @@ class CollectionController extends Controller 'view' => ['GET'], 'create' => ['POST'], 'delete' => ['POST'], - 'access' => ['GET'], - 'upload' => ['POST'], + 'access' => ['GET'], //剩余空间检查√ + 'upload' => ['POST'], //剩余空间检查√ ], ], ] @@ -179,6 +180,8 @@ class CollectionController extends Controller throw new NotFoundHttpException('请求的文件收集任务已失效或不存在'); } elseif (!is_dir(Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . $model->user_id . '/' . $model->folder_path)) { throw new NotFoundHttpException('收集任务的目标路径不存在'); + } elseif (!FileSizeHelper::hasEnoughSpace(0, $model->user_id)) { + throw new NotFoundHttpException('由于该用户存储空间已耗尽,请求的文件收集任务暂停'); } elseif ($secret === null) { return $this->render('_gateway', [ 'model' => new CollectionTasks(), @@ -219,6 +222,9 @@ class CollectionController extends Controller $task = $this->findModel($taskId, true); //CollectionTasks::findOne($taskId); $userId = $task->user_id; $folderPath = $task->folder_path; + if (!FileSizeHelper::hasEnoughSpace(0, $userId)) { + throw new NotFoundHttpException('由于该用户存储空间已耗尽,请求的文件收集任务暂停'); + } // 创建一个新的CollectionUploaded模型实例,并设置其属性值 $model = new CollectionUploaded(); diff --git a/controllers/HomeController.php b/controllers/HomeController.php index 8c1421d..de87c22 100644 --- a/controllers/HomeController.php +++ b/controllers/HomeController.php @@ -50,16 +50,16 @@ class HomeController extends Controller 'actions' => [ 'index' => ['GET'], 'download' => ['GET'], - 'preview' =>['GET'], + 'preview' => ['GET'], 'rename' => ['POST'], 'delete' => ['POST'], - 'upload' => ['POST'], + 'upload' => ['POST'], //剩余空间检查√ 'new-folder' => ['POST'], 'download-folder' => ['GET'], 'multi-ff-zip-dl' => ['POST'], - 'zip' => ['POST'], - 'unzip' => ['POST'], - 'paste' => ['POST'], + 'zip' => ['POST'], //剩余空间检查√ + 'unzip' => ['POST'], //剩余空间检查√ + 'paste' => ['POST'], //剩余空间检查√ ], ], ] @@ -222,6 +222,7 @@ class HomeController extends Controller // 结束脚本执行 exit; } + /** * 重命名文件或文件夹 * @return string|Response|null @@ -368,6 +369,9 @@ class HomeController extends Controller if (!preg_match($this->pattern, $model->uploadFile->fullPath) || str_contains($model->uploadFile->fullPath, '..')) { continue; } + if (!FileSizeHelper::hasEnoughSpace($model->uploadFile->size)) { + continue; + } if ($model->upload()) { $successCount++; } @@ -375,21 +379,21 @@ class HomeController extends Controller if ($sp === 'editSaving') { if ($successCount === $totalCount) { Yii::$app->response->statusCode = 200; - return $this->asJson(['status' => 200, 'message' => 'All files uploaded successfully.']); - } else{ - Yii::$app->response->statusCode = 500; - return $this->asJson(['status' => 500, 'message' => 'Failed to upload files.']); - } - }else { - if ($successCount === $totalCount) { - Yii::$app->session->setFlash('success', 'All files uploaded successfully.'); - } elseif ($successCount > 0) { - Yii::$app->session->setFlash('warning', 'Some files uploaded successfully.'); + return $this->asJson(['status' => 200, 'message' => '文件上传成功']); } else { - Yii::$app->session->setFlash('error', 'Failed to upload files.'); + Yii::$app->response->statusCode = 500; + return $this->asJson(['status' => 500, 'message' => '文件上传失败']); + } + } else { + if ($successCount === $totalCount) { + Yii::$app->session->setFlash('success', '文件上传成功'); + } elseif ($successCount > 0) { + Yii::$app->session->setFlash('warning', '部分文件上传失败,这可能是用户剩余空间不足导致'); + } else { + Yii::$app->session->setFlash('error', '文件上传失败,这可能是用户剩余空间不足导致'); } //返回状态码200 - return Yii::$app->response->statusCode = 200; // 如果出错请删掉return} + return Yii::$app->response->statusCode = 200; } } @@ -572,7 +576,7 @@ class HomeController extends Controller { $model = new ZipForm(); $relativePaths = json_decode(Yii::$app->request->post('relativePath'), true); - $targetDirectory = Yii::$app->request->post('targetDirectory')??'.'; + $targetDirectory = Yii::$app->request->post('targetDirectory') ?? '.'; if ($model->load(Yii::$app->request->post()) && $model->validate()) { if (str_contains($targetDirectory, '..')) { throw new NotFoundHttpException('Invalid target directory.'); @@ -593,7 +597,16 @@ class HomeController extends Controller $zipPath = Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . Yii::$app->user->id . '/' . $targetDirectory . '/' . $model->zipFilename . '.' . $model->zipFormat; try { UnifiedArchive::create($absolutePaths, $zipPath); - Yii::$app->session->setFlash('success', '打包成功'); + // 获取新的压缩文件的大小 + $zipSize = filesize($zipPath); + // 检查新的压缩文件的大小是否超过用户的存储限制 + if (!FileSizeHelper::hasEnoughSpace()) { + // 如果超过,删除这个新的压缩文件,并显示一个错误消息 + unlink($zipPath); + Yii::$app->session->setFlash('error', '打包失败,空间不足'); + } else { + Yii::$app->session->setFlash('success', '打包成功'); + } } catch (FileAlreadyExistsException) { Yii::$app->session->setFlash('error', '目标文件夹已存在同名压缩档案'); } catch (UnsupportedOperationException) { @@ -629,15 +642,25 @@ class HomeController extends Controller try { $archive->extract($targetDirectory); - Yii::$app->session->setFlash('success', 'Folder created successfully.'); Yii::$app->response->format = Response::FORMAT_JSON; - return [ - 'status' => 200, - 'directory' => pathinfo($relativePath, PATHINFO_FILENAME) . '_' . $now_time, - ]; + if (!FileSizeHelper::hasEnoughSpace()) { + $this->deleteDirectory($targetDirectory); + Yii::$app->session->setFlash('error', '解压失败,空间不足'); + return [ + 'status' => 500, + 'directory' => pathinfo($relativePath, PATHINFO_FILENAME) . '_' . $now_time, + 'parentDirectory' => dirname($relativePath), + ]; + }else{ + Yii::$app->session->setFlash('success', '解压成功'); + return [ + 'status' => 200, + 'directory' => pathinfo($relativePath, PATHINFO_FILENAME) . '_' . $now_time, + ]; + } } catch (ArchiveExtractionException) { $this->deleteDirectory($targetDirectory); - Yii::$app->session->setFlash('error', 'Failed to extract the archive.'); + Yii::$app->session->setFlash('error', '解压过程中出现错误'); Yii::$app->response->format = Response::FORMAT_JSON; return [ 'status' => 500, @@ -676,6 +699,13 @@ class HomeController extends Controller // 检查目标路径是否已经存在同名文件或目录 if ($operation === 'copy' && file_exists($targetPath)) { + $sourceFileSize = filesize($sourcePath); + + // 检查是否有足够的空间进行复制操作 + if (!FileSizeHelper::hasEnoughSpace($sourceFileSize)) { + Yii::$app->session->setFlash('error', 'Not enough space to copy the file.'); + return $this->redirect(['index', 'directory' => $targetDirectory]); + } $pathInfo = pathinfo($targetPath); $i = 1; do { @@ -688,7 +718,11 @@ class HomeController extends Controller // 根据操作类型执行相应的操作 if ($operation === 'copy') { - // 如果是复制操作 + $sourceSize = is_dir($sourcePath) ? FileSizeHelper::getDirectorySize($sourcePath) : filesize($sourcePath); + if (!FileSizeHelper::hasEnoughSpace($sourceSize)) { + Yii::$app->session->setFlash('error', 'Not enough space to copy.'); + return $this->redirect(['index', 'directory' => $targetDirectory]); + } if (is_dir($sourcePath)) { // 如果源路径是目录,递归复制目录 if (!$this->copyDirectory($sourcePath, $targetPath)) { diff --git a/models/UploadForm.php b/models/UploadForm.php index f78ce21..02a247e 100644 --- a/models/UploadForm.php +++ b/models/UploadForm.php @@ -5,6 +5,7 @@ namespace app\models; +use app\utils\FileSizeHelper; use Yii; use yii\base\Model; use yii\web\UploadedFile; @@ -14,14 +15,14 @@ class UploadForm extends Model public UploadedFile|null $uploadFile; public $targetDir; //相对路径 - public function rules() + public function rules(): array { return [ [['uploadFile'], 'file', 'skipOnEmpty' => false, 'checkExtensionByMimeType' => false], //这规则奇怪的放走近科学都可以拍好几集了 ]; } - public function upload() + public function upload(): bool { if ($this->validate()) { if ($this->targetDir === null) { @@ -40,6 +41,9 @@ class UploadForm extends Model if (!is_dir($directory)) { mkdir($directory, 0777, true); } + if (!FileSizeHelper::hasEnoughSpace($this->uploadFile->size)) { + return false; + } $this->uploadFile->saveAs($absolutePath . '/' . $fileName); return true; } else { diff --git a/utils/FileSizeHelper.php b/utils/FileSizeHelper.php index 63c3a20..b9e8dac 100644 --- a/utils/FileSizeHelper.php +++ b/utils/FileSizeHelper.php @@ -2,8 +2,11 @@ namespace app\utils; +use app\models\User; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; +use Yii; +use yii\web\NotFoundHttpException; class FileSizeHelper { @@ -25,6 +28,30 @@ class FileSizeHelper return $size; } + /** + * 判断用户home是否有足够的容量存放文件 + * @param int $file_size 文件大小B(可选,如果文件已经添加到网盘时,不需要这个参数) + * @return bool + */ + public static function hasEnoughSpace(int $file_size = 0, int $user_id = null): bool + { + if ($user_id === null) { + $user_id = Yii::$app->user->id; + } + $userHomeDir = Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . $user_id; + $userHomeDirSize_MB = self::getDirectorySize($userHomeDir) / 1024 / 1024; + $file_size_MB = $file_size / 1024 / 1024; + $user = User::findOne($user_id); + if ($user === null) { + throw new NotFoundHttpException('User not found.'); + } + $limit = $user->storage_limit; + if ($limit == -1) { + return true; + } + return $userHomeDirSize_MB + $file_size_MB <= $limit; + } + /** * @param $bytes * @param $precision @@ -50,7 +77,7 @@ class FileSizeHelper */ public static function formatMegaBytes($megabytes, $precision = 2): string { - if($megabytes===-1){ + if ($megabytes === -1) { return '∞'; } $bytes = $megabytes * pow(1024, 2); // Convert megabytes to bytes