perf: 优化打包下载

This commit is contained in:
kuaifan
2024-01-03 20:48:49 +08:00
parent ecdabc668d
commit 846fdcf145
7 changed files with 84 additions and 96 deletions

View File

@@ -13,6 +13,8 @@ use App\Models\FileUser;
use App\Models\User;
use App\Module\Base;
use App\Module\Ihttp;
use Response;
use Session;
use Swoole\Coroutine;
use Carbon\Carbon;
use Redirect;
@@ -991,9 +993,33 @@ class FileController extends AbstractController
*/
public function download__pack()
{
$key = Request::input('key');
if ($key) {
$userid = Session::get('file::pack:userid');
if (empty($userid)) {
return Base::ajaxError("请求已过期,请重新导出!", [], 0, 502);
}
//
$array = Base::string2array(base64_decode(urldecode($key)));
$file = $array['file'];
if (empty($file) || !file_exists(storage_path($file))) {
return Base::ajaxError("文件不存在!", [], 0, 502);
}
return Response::download(storage_path($file));
}
$user = User::auth();
$ids = Request::input('ids');
$downName = Request::input('name');
$fileName = Request::input('name');
$fileName = preg_replace("/[\/\\\:\*\?\"\<\>\|]/", "", $fileName);
if (empty($fileName)) {
$fileName = 'Package_' . $user->userid;
}
$fileName .= '_' . Base::time() . '.zip';
$filePath = "temp/file/pack/" . date("Ym", Base::time());
$zipFile = "app/" . $filePath . "/" . $fileName;
$zipPath = storage_path($zipFile);
if (!is_array($ids) || empty($ids)) {
return Base::retError('请选择下载的文件或文件夹');
@@ -1001,9 +1027,6 @@ class FileController extends AbstractController
if (count($ids) > 100) {
return Base::retError('一次最多可以下载100个文件或文件夹');
}
if (count($ids) > 100) {
return Base::retError('一次最多可以下载100个文件或文件夹');
}
$files = [];
$totalSize = 0;
@@ -1017,23 +1040,28 @@ class FileController extends AbstractController
return Base::retError('文件总大小已超过1GB,请分批下载');
}
$base64 = base64_encode(Base::array2string([
'file' => $zipFile,
]));
$fileUrl = Base::fillUrl('api/file/download/pack?key=' . urlencode($base64));
Session::put('file::pack:userid', $user->userid);
$zip = new \ZipArchive();
$zipName = 'tmp/file/' . date("Ym") . '/' . $user->userid . '/' . $downName;
$zipPath = public_path($zipName);
Base::makeDir(dirname($zipPath));
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return Base::retError('创建压缩文件失败');
}
go(function() use ($user, $zip, $files, $downName, $zipName) {
go(function () use ($zipPath, $fileUrl, $user, $zip, $files, $fileName, $zipFile) {
Coroutine::sleep(0.1);
// 压缩进度
$progress = 0;
$zip->registerProgressCallback(0.05, function($ratio) use ($downName, &$progress) {
$zip->registerProgressCallback(0.05, function ($ratio) use ($fileUrl, $fileName, &$progress) {
$progress = round($ratio * 100);
File::filePushMsg('compress', [
'name'=> $downName,
'name' => $fileName,
'url' => $fileUrl,
'progress' => $progress
]);
});
@@ -1045,7 +1073,8 @@ class FileController extends AbstractController
//
if ($progress < 100) {
File::filePushMsg('compress', [
'name'=> $downName,
'name' => $fileName,
'url' => $fileUrl,
'progress' => 100
]);
}
@@ -1057,39 +1086,17 @@ class FileController extends AbstractController
if ($dialog = WebSocketDialog::checkUserDialog($botUser, $user->userid)) {
$text = "<b>文件下载打包已完成。</b>";
$text .= "\n\n";
$text .= "文件名:{$downName}";
$text .= "文件名:{$fileName}";
$text .= "\n";
$text .= "下载地址:".Base::fillUrl($zipName);
$text .= "文件大小:".Base::twoFloat(filesize($zipPath) / 1024, true)."KB";
$text .= "\n";
$text .= '<a href="' . $fileUrl . '" target="_blank"><button type="button" class="ivu-btn ivu-btn-warning" style="margin-top: 10px;"><span>立即下载</span></button></a>';
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, true);
}
});
return Base::retSuccess('success');
}
/**
* @api {get} api/file/download/confirm 20. 确认下载
*
* @apiDescription 需要token身份
* @apiVersion 1.0.0
* @apiGroup file
* @apiName download__confirm
*
* @apiParam {String} [name] 下载文件名
*
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
*/
public function download__confirm()
{
$user = User::auth();
$downName = Request::input('name');
$zipName = 'tmp/file/' . date("Ym") . '/' . $user->userid . '/' . $downName;
$zipPath = public_path($zipName);
if (!file_exists($zipPath)) {
abort(403, "The file does not exist.");
}
return response()->download($zipPath);
return Base::retSuccess('success', [
'name' => $fileName,
'url' => $fileUrl,
]);
}
}

View File

@@ -1200,7 +1200,7 @@ class ProjectController extends AbstractController
if (Carbon::parse($time[1])->timestamp - Carbon::parse($time[0])->timestamp > 90 * 86400) {
return Base::retError('时间范围限制最大90天');
}
go(function() use ($user, $userid, $time, $type) {
go(function () use ($user, $userid, $time, $type) {
Coroutine::sleep(0.1);
$headings = [];
$headings[] = '任务ID';
@@ -1324,10 +1324,10 @@ class ProjectController extends AbstractController
$sheets = [];
foreach ($userid as $ownerid) {
$data = $datas[$ownerid] ?? [
'nickname' => Base::filterEmoji(User::userid2nickname($ownerid)),
'styles' => ["A1:P1" => ["font" => ["bold" => true]]],
'data' => [],
];
'nickname' => Base::filterEmoji(User::userid2nickname($ownerid)),
'styles' => ["A1:P1" => ["font" => ["bold" => true]]],
'data' => [],
];
$title = (count($sheets) + 1) . "." . ($data['nickname'] ?: $ownerid);
$sheets[] = BillExport::create()->setTitle($title)->setHeadings($headings)->setData($data['data'])->setStyles($data['styles']);
}
@@ -1369,14 +1369,14 @@ class ProjectController extends AbstractController
$text .= "\n\n";
$text .= "文件名:{$fileName}";
$text .= "\n";
$text .= "文件大小:".Base::twoFloat(filesize($zipPath) / 1024, true)."KB";
$text .= "文件大小:" . Base::twoFloat(filesize($zipPath) / 1024, true) . "KB";
$text .= "\n";
$text .= '<button class="ivu-btn" style="margin-top: 10px;"><a href="'.$fileUrl.'" target="_blank">立即下载</a></button>';
$text .= '<a href="' . $fileUrl . '" target="_blank"><button type="button" class="ivu-btn ivu-btn-warning" style="margin-top: 10px;"><span>立即下载</span></button></a>';
WebSocketDialogMsg::sendMsg(null, $dialog->id, 'text', ['text' => $text], $botUser->userid, false, false, true);
}
}
});
return Base::retSuccess('success',['msg' => '正在打包,请留意系统消息']);
return Base::retSuccess('success', ['msg' => '正在打包,请留意系统消息。']);
}
/**