From 930f55b0809ba7a23cadc03026b042e64d7509b4 Mon Sep 17 00:00:00 2001 From: ganzizi Date: Fri, 10 Nov 2023 19:34:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=8B=E8=BD=BD=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E5=A4=9A=E6=96=87=E4=BB=B6=E5=8E=8B=E7=BC=A9=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 3 +- app/Http/Controllers/Api/FileController.php | 52 ++++++++++ app/Models/File.php | 96 ++++++++++++++++++- resources/assets/js/pages/manage/file.vue | 29 ++++++ 4 files changed, 177 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index 02331084e..ab51c0ffc 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -868,8 +868,7 @@ class DialogController extends AbstractController } /** - * @api {post} api/dialog/msg/sendfiles 18. 群发文件上传 - * @api {post} api/dialog/msg/sendfiles 18. 群发文件上传 + * @api {post} api/dialog/msg/sendfiles 19. 群发文件上传 * * @apiDescription 需要token身份 * @apiVersion 1.0.0 diff --git a/app/Http/Controllers/Api/FileController.php b/app/Http/Controllers/Api/FileController.php index 049d29b99..0accc97eb 100755 --- a/app/Http/Controllers/Api/FileController.php +++ b/app/Http/Controllers/Api/FileController.php @@ -14,6 +14,7 @@ use App\Module\Ihttp; use Carbon\Carbon; use Redirect; use Request; +use ZipArchive; /** * @apiDefine file @@ -969,4 +970,55 @@ class FileController extends AbstractController // return Base::retSuccess('success', $fileLink); } + + /** + * @api {get} api/file/download/zip 19. 压缩下载 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup file + * @apiName download__zip + * + * @apiParam {Array} [ids] 文件ID,格式: [id, id2, id3] + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function download__zip() + { + $user = User::auth(); + $ids = Request::input('ids'); + if (!is_array($ids) || empty($ids)) { + return Base::retError('Please select the downloaded file or folder'); + } + + if (count($ids) > 100) { + return Base::retError('You can only download up to 100 files or folders at a time'); + } + + $files = []; + AbstractModel::transaction(function() use ($user, $ids, &$files) { + foreach ($ids as $id) { + $files[] = File::getFilesTree(intval($id), $user, 0); + } + }); + + $zip = new \ZipArchive(); + $zipName = 'temp/download/' . date("Ym") . '/' . $user->userid . '/file_' . date("YmdHis") . '.zip'; + $zipPath = storage_path('app/'.$zipName); + Base::makeDir(dirname($zipPath)); + + if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { + return Base::retError('创建压缩文件失败'); + } + + array_walk($files, function($file) use ($zip) { + File::addFileTreeToZip($zip, $file); + }); + + $zip->close(); + + return response()->download($zipPath, 'file_'. date("YmdHis") .'.zip')->deleteFileAfterSend(true); + } } diff --git a/app/Models/File.php b/app/Models/File.php index e25b5032c..068adeba1 100644 --- a/app/Models/File.php +++ b/app/Models/File.php @@ -317,7 +317,7 @@ class File extends AbstractModel $data['full_name'] = $webkitRelativePath ?: $data['name']; // $addItem[] = $data; - + return ['data'=>$data,'addItem'=>$addItem]; }); } @@ -832,4 +832,98 @@ class File extends AbstractModel } }); } + + /** + * 获取文件树 + * + * @param int $fileId + * @param User $user + * @param int $permission + * @param string $path + * @return object + */ + public static function getFilesTree(int $fileId, User $user, $permission = 1, $path = '') { + $file = File::permissionFind($fileId, $user, $permission); + $file->path = ltrim($path . '/' . $file->name, '/'); + $file->children = []; + if ($file->type == 'folder') { + $files = $file->getFileList($user, $fileId, 'all', false); + foreach ($files as &$childFile) { + $childFile['path'] = $file->path . '/' . $childFile['name']; + if ($childFile['type'] == 'folder') { + $childFile['children'] = self::getFilesTree($childFile['id'], $user, $permission, $file->path); + } + } + $file->children = $files; + } + $totalSize = self::calculateTotalSize($file); + if ($totalSize > 1024 * 1024 * 1024) { // 1GB + throw new ApiException('The total file size has exceeded 1GB, please download in batches'); + } + return $file; + } + + /** + * 计算文件夹文件总大小 + * + * @param [type] $fileTree + * @return float|int + */ + public static function calculateTotalSize($fileTree) { + $totalSize = 0; + if ($fileTree->type != 'folder') { + $totalSize += $fileTree->size; + } else { + foreach ($fileTree->children as $childFile) { + $totalSize += self::calculateTotalSize((object)$childFile); + } + } + return $totalSize; + } + + /** + * 文件夹文件添加到压缩文件 + * + * @param [type] $zip + * @param object $file + * @return void + */ + public static function addFileTreeToZip($zip, $file) + { + if ($file->type != 'folder') { + $content = FileContent::whereFid($file->id)->orderByDesc('id')->first(); + $content = Base::json2array($content?->content ?: []); + $typeExtensions = [ + 'word' => 'docx', + 'excel' => 'xlsx', + 'ppt' => 'pptx', + ]; + if (array_key_exists($file->type, $typeExtensions)) { + $filePath = empty($content) ? public_path('assets/office/empty.' . $typeExtensions[$file->type]) : public_path($content['url']); + } + + $relativePath = $file->path . '.' . $file->ext; + if (file_exists($filePath)) { + $zip->addFile($filePath, $relativePath); + } else { + if (empty($content['url'])) { + $zip->addFromString($relativePath, $content['content']); + } else { + $filePath = public_path($content['url']); + $zip->addFile($filePath, $relativePath); + } + } + } else { + if (isset($file->children)) { + foreach ($file->children as $childFile) { + try { + self::addFileTreeToZip($zip, (object)$childFile); + } catch (\Exception $e) { + } + } + } + // 在压缩包中创建文件夹 + $zip->addEmptyDir($file->path); + } + } } diff --git a/resources/assets/js/pages/manage/file.vue b/resources/assets/js/pages/manage/file.vue index 7b2781649..1d7964afc 100644 --- a/resources/assets/js/pages/manage/file.vue +++ b/resources/assets/js/pages/manage/file.vue @@ -49,6 +49,10 @@ {{$L('剪切')}} +