加入剩余空间的判断

*应该没有bug了吧
This commit is contained in:
Chenx221 2024-03-10 13:20:32 +08:00
parent 9eb947b81b
commit d0b7c84bba
Signed by: chenx221
GPG Key ID: D7A9EC07024C3021
4 changed files with 102 additions and 31 deletions

View File

@ -5,6 +5,7 @@ namespace app\controllers;
use app\models\CollectionTasks; use app\models\CollectionTasks;
use app\models\CollectionSearch; use app\models\CollectionSearch;
use app\models\CollectionUploaded; use app\models\CollectionUploaded;
use app\utils\FileSizeHelper;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
use RuntimeException; use RuntimeException;
use Yii; use Yii;
@ -52,8 +53,8 @@ class CollectionController extends Controller
'view' => ['GET'], 'view' => ['GET'],
'create' => ['POST'], 'create' => ['POST'],
'delete' => ['POST'], 'delete' => ['POST'],
'access' => ['GET'], 'access' => ['GET'], //剩余空间检查√
'upload' => ['POST'], 'upload' => ['POST'], //剩余空间检查√
], ],
], ],
] ]
@ -179,6 +180,8 @@ class CollectionController extends Controller
throw new NotFoundHttpException('请求的文件收集任务已失效或不存在'); throw new NotFoundHttpException('请求的文件收集任务已失效或不存在');
} elseif (!is_dir(Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . $model->user_id . '/' . $model->folder_path)) { } elseif (!is_dir(Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . $model->user_id . '/' . $model->folder_path)) {
throw new NotFoundHttpException('收集任务的目标路径不存在'); throw new NotFoundHttpException('收集任务的目标路径不存在');
} elseif (!FileSizeHelper::hasEnoughSpace(0, $model->user_id)) {
throw new NotFoundHttpException('由于该用户存储空间已耗尽,请求的文件收集任务暂停');
} elseif ($secret === null) { } elseif ($secret === null) {
return $this->render('_gateway', [ return $this->render('_gateway', [
'model' => new CollectionTasks(), 'model' => new CollectionTasks(),
@ -219,6 +222,9 @@ class CollectionController extends Controller
$task = $this->findModel($taskId, true); //CollectionTasks::findOne($taskId); $task = $this->findModel($taskId, true); //CollectionTasks::findOne($taskId);
$userId = $task->user_id; $userId = $task->user_id;
$folderPath = $task->folder_path; $folderPath = $task->folder_path;
if (!FileSizeHelper::hasEnoughSpace(0, $userId)) {
throw new NotFoundHttpException('由于该用户存储空间已耗尽,请求的文件收集任务暂停');
}
// 创建一个新的CollectionUploaded模型实例并设置其属性值 // 创建一个新的CollectionUploaded模型实例并设置其属性值
$model = new CollectionUploaded(); $model = new CollectionUploaded();

View File

@ -50,16 +50,16 @@ class HomeController extends Controller
'actions' => [ 'actions' => [
'index' => ['GET'], 'index' => ['GET'],
'download' => ['GET'], 'download' => ['GET'],
'preview' =>['GET'], 'preview' => ['GET'],
'rename' => ['POST'], 'rename' => ['POST'],
'delete' => ['POST'], 'delete' => ['POST'],
'upload' => ['POST'], 'upload' => ['POST'], //剩余空间检查√
'new-folder' => ['POST'], 'new-folder' => ['POST'],
'download-folder' => ['GET'], 'download-folder' => ['GET'],
'multi-ff-zip-dl' => ['POST'], 'multi-ff-zip-dl' => ['POST'],
'zip' => ['POST'], 'zip' => ['POST'], //剩余空间检查√
'unzip' => ['POST'], 'unzip' => ['POST'], //剩余空间检查√
'paste' => ['POST'], 'paste' => ['POST'], //剩余空间检查√
], ],
], ],
] ]
@ -222,6 +222,7 @@ class HomeController extends Controller
// 结束脚本执行 // 结束脚本执行
exit; exit;
} }
/** /**
* 重命名文件或文件夹 * 重命名文件或文件夹
* @return string|Response|null * @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, '..')) { if (!preg_match($this->pattern, $model->uploadFile->fullPath) || str_contains($model->uploadFile->fullPath, '..')) {
continue; continue;
} }
if (!FileSizeHelper::hasEnoughSpace($model->uploadFile->size)) {
continue;
}
if ($model->upload()) { if ($model->upload()) {
$successCount++; $successCount++;
} }
@ -375,21 +379,21 @@ class HomeController extends Controller
if ($sp === 'editSaving') { if ($sp === 'editSaving') {
if ($successCount === $totalCount) { if ($successCount === $totalCount) {
Yii::$app->response->statusCode = 200; Yii::$app->response->statusCode = 200;
return $this->asJson(['status' => 200, 'message' => 'All files uploaded successfully.']); return $this->asJson(['status' => 200, 'message' => '文件上传成功']);
} 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.');
} else { } 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 //返回状态码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(); $model = new ZipForm();
$relativePaths = json_decode(Yii::$app->request->post('relativePath'), true); $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 ($model->load(Yii::$app->request->post()) && $model->validate()) {
if (str_contains($targetDirectory, '..')) { if (str_contains($targetDirectory, '..')) {
throw new NotFoundHttpException('Invalid target directory.'); 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; $zipPath = Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . Yii::$app->user->id . '/' . $targetDirectory . '/' . $model->zipFilename . '.' . $model->zipFormat;
try { try {
UnifiedArchive::create($absolutePaths, $zipPath); 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) { } catch (FileAlreadyExistsException) {
Yii::$app->session->setFlash('error', '目标文件夹已存在同名压缩档案'); Yii::$app->session->setFlash('error', '目标文件夹已存在同名压缩档案');
} catch (UnsupportedOperationException) { } catch (UnsupportedOperationException) {
@ -629,15 +642,25 @@ class HomeController extends Controller
try { try {
$archive->extract($targetDirectory); $archive->extract($targetDirectory);
Yii::$app->session->setFlash('success', 'Folder created successfully.');
Yii::$app->response->format = Response::FORMAT_JSON; Yii::$app->response->format = Response::FORMAT_JSON;
return [ if (!FileSizeHelper::hasEnoughSpace()) {
'status' => 200, $this->deleteDirectory($targetDirectory);
'directory' => pathinfo($relativePath, PATHINFO_FILENAME) . '_' . $now_time, 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) { } catch (ArchiveExtractionException) {
$this->deleteDirectory($targetDirectory); $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; Yii::$app->response->format = Response::FORMAT_JSON;
return [ return [
'status' => 500, 'status' => 500,
@ -676,6 +699,13 @@ class HomeController extends Controller
// 检查目标路径是否已经存在同名文件或目录 // 检查目标路径是否已经存在同名文件或目录
if ($operation === 'copy' && file_exists($targetPath)) { 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); $pathInfo = pathinfo($targetPath);
$i = 1; $i = 1;
do { do {
@ -688,7 +718,11 @@ class HomeController extends Controller
// 根据操作类型执行相应的操作 // 根据操作类型执行相应的操作
if ($operation === 'copy') { 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 (is_dir($sourcePath)) {
// 如果源路径是目录,递归复制目录 // 如果源路径是目录,递归复制目录
if (!$this->copyDirectory($sourcePath, $targetPath)) { if (!$this->copyDirectory($sourcePath, $targetPath)) {

View File

@ -5,6 +5,7 @@
namespace app\models; namespace app\models;
use app\utils\FileSizeHelper;
use Yii; use Yii;
use yii\base\Model; use yii\base\Model;
use yii\web\UploadedFile; use yii\web\UploadedFile;
@ -14,14 +15,14 @@ class UploadForm extends Model
public UploadedFile|null $uploadFile; public UploadedFile|null $uploadFile;
public $targetDir; //相对路径 public $targetDir; //相对路径
public function rules() public function rules(): array
{ {
return [ return [
[['uploadFile'], 'file', 'skipOnEmpty' => false, 'checkExtensionByMimeType' => false], //这规则奇怪的放走近科学都可以拍好几集了 [['uploadFile'], 'file', 'skipOnEmpty' => false, 'checkExtensionByMimeType' => false], //这规则奇怪的放走近科学都可以拍好几集了
]; ];
} }
public function upload() public function upload(): bool
{ {
if ($this->validate()) { if ($this->validate()) {
if ($this->targetDir === null) { if ($this->targetDir === null) {
@ -40,6 +41,9 @@ class UploadForm extends Model
if (!is_dir($directory)) { if (!is_dir($directory)) {
mkdir($directory, 0777, true); mkdir($directory, 0777, true);
} }
if (!FileSizeHelper::hasEnoughSpace($this->uploadFile->size)) {
return false;
}
$this->uploadFile->saveAs($absolutePath . '/' . $fileName); $this->uploadFile->saveAs($absolutePath . '/' . $fileName);
return true; return true;
} else { } else {

View File

@ -2,8 +2,11 @@
namespace app\utils; namespace app\utils;
use app\models\User;
use RecursiveDirectoryIterator; use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
use Yii;
use yii\web\NotFoundHttpException;
class FileSizeHelper class FileSizeHelper
{ {
@ -25,6 +28,30 @@ class FileSizeHelper
return $size; 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 $bytes
* @param $precision * @param $precision
@ -50,7 +77,7 @@ class FileSizeHelper
*/ */
public static function formatMegaBytes($megabytes, $precision = 2): string public static function formatMegaBytes($megabytes, $precision = 2): string
{ {
if($megabytes===-1){ if ($megabytes === -1) {
return '∞'; return '∞';
} }
$bytes = $megabytes * pow(1024, 2); // Convert megabytes to bytes $bytes = $megabytes * pow(1024, 2); // Convert megabytes to bytes