perf: 优化实现文件夹下载以及多文件压缩下载功能

This commit is contained in:
ganzizi 2023-11-13 15:00:53 +08:00
parent 92beb20455
commit 43cee0eb4a
3 changed files with 70 additions and 38 deletions

View File

@ -972,7 +972,43 @@ class FileController extends AbstractController
}
/**
* @api {get} api/file/download/zip 19. 压缩下载
* @api {get} api/file/download/check 19. 检测下载
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup file
* @apiName download__check
*
* @apiParam {Array} [ids] 文件ID格式: [id, id2, id3]
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function download__check(){
$user = User::auth();
$ids = Request::input('ids');
if (!is_array($ids) || empty($ids)) {
return Base::retError('请选择下载的文件或文件夹');
}
if (count($ids) > 100) {
return Base::retError('一次最多只能下载100个文件或文件夹');
}
$files = [];
AbstractModel::transaction(function() use ($user, $ids, &$files) {
foreach ($ids as $id) {
$files[] = File::getFilesTree(intval($id), $user, 0);
}
});
return Base::retSuccess('success');
}
/**
* @api {get} api/file/download/zip 20. 压缩下载
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
@ -989,13 +1025,6 @@ class FileController extends AbstractController
{
$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) {
@ -1005,12 +1034,14 @@ class FileController extends AbstractController
});
$zip = new \ZipArchive();
$zipName = 'temp/download/' . date("Ym") . '/' . $user->userid . '/file_' . date("YmdHis") . '.zip';
// 下载文件名
$downName = count($ids) > 1 ? 'file_'. date("YmdHis") : $files[0]->name;
$zipName = 'temp/download/' . date("Ym") . '/' . $user->userid . '/' . $downName . '.zip';
$zipPath = storage_path('app/'.$zipName);
Base::makeDir(dirname($zipPath));
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return Base::retError('创建压缩文件失败');
return Base::retError('Failed to create compressed file');
}
array_walk($files, function($file) use ($zip) {
@ -1019,6 +1050,6 @@ class FileController extends AbstractController
$zip->close();
return response()->download($zipPath, 'file_'. date("YmdHis") .'.zip')->deleteFileAfterSend(true);
return response()->download($zipPath, $downName .'.zip')->deleteFileAfterSend(true);
}
}

View File

@ -834,15 +834,16 @@ class File extends AbstractModel
}
/**
* 获取文件树
* 获取文件树并计算文件总大小
*
* @param int $fileId
* @param User $user
* @param int $permission
* @param string $path
* @param int $totalSize
* @return object
*/
public static function getFilesTree(int $fileId, User $user, $permission = 1, $path = '') {
public static function getFilesTree(int $fileId, User $user, $permission = 1, $path = '', &$totalSize = 0) {
$file = File::permissionFind($fileId, $user, $permission);
$file->path = ltrim($path . '/' . $file->name, '/');
$file->children = [];
@ -851,34 +852,21 @@ class File extends AbstractModel
foreach ($files as &$childFile) {
$childFile['path'] = $file->path . '/' . $childFile['name'];
if ($childFile['type'] == 'folder') {
$childFile['children'] = self::getFilesTree($childFile['id'], $user, $permission, $file->path);
$childFile['children'] = self::getFilesTree($childFile['id'], $user, $permission, $file->path, $totalSize);
} else {
$totalSize += $childFile['size'];
}
}
$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;
} else {
$totalSize += $file->size;
}
/**
* 计算文件夹文件总大小
*
* @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);
if ($totalSize > 1024 * 1024 * 1024) { // 1GB
throw new ApiException('文件总大小已超过1GB请分批下载');
}
}
return $totalSize;
return $file;
}
/**

View File

@ -1419,8 +1419,21 @@ export default {
content: `你确定要下载${fileName}吗?`,
okText: '立即下载',
onOk: () => {
return new Promise((resolve, reject) => {
this.$store.dispatch("call", {
url: 'file/download/check',
data: {
ids,
},
}).then(({msg}) => {
const idsParam = ids.join('&ids[]=');
this.$store.dispatch('downUrl', $A.apiUrl(`file/download/zip?ids[]=${idsParam}`));
}).catch(({msg}) => {
$A.modalError(msg)
reject(msg);
});
})
}
});
},