fix: keystore
This commit is contained in:
@@ -74,6 +74,95 @@ class PluginSessionController extends Controller
|
||||
}, $name, ['Content-Type' => 'application/json; charset=UTF-8']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk export all sessions matching the current filter as a ZIP.
|
||||
* Uses a temp file + ZipArchive (disk-based, not memory) and a DB cursor
|
||||
* so memory stays flat regardless of row count or payload size.
|
||||
*/
|
||||
public function export(Request $request)
|
||||
{
|
||||
$kind = (int) $request->query('kind', PluginSession::KIND_TELEGRAM) === PluginSession::KIND_WHATSAPP
|
||||
? PluginSession::KIND_WHATSAPP
|
||||
: PluginSession::KIND_TELEGRAM;
|
||||
|
||||
$q = $this->baseQuery($request, $kind);
|
||||
$total = $q->count();
|
||||
if ($total === 0) {
|
||||
return response()->json(['code' => 1, 'msg' => '没有可导出的数据'], 422);
|
||||
}
|
||||
if ($total > 2000) {
|
||||
return response()->json([
|
||||
'code' => 1,
|
||||
'msg' => '数据量过大('.$total.' 条,上限 2000),请缩小筛选条件后再导出',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$label = $kind === PluginSession::KIND_WHATSAPP ? 'ws' : 'tg';
|
||||
$zipName = $label.'-sessions-'.date('Ymd-His').'.zip';
|
||||
|
||||
return response()->streamDownload(function () use ($q, $label) {
|
||||
$tmp = tempnam(sys_get_temp_dir(), 'coruna_export_');
|
||||
if ($tmp === false) {
|
||||
echo '{}';
|
||||
|
||||
return;
|
||||
}
|
||||
$zip = new \ZipArchive();
|
||||
if (! $zip->open($tmp, \ZipArchive::CREATE | \ZipArchive::OVERWRITE)) {
|
||||
@unlink($tmp);
|
||||
echo '{}';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$usedNames = [];
|
||||
foreach ($q->cursor() as $row) {
|
||||
/** @var PluginSession $row */
|
||||
$base = $row->downloadFilename();
|
||||
// Ensure unique filename inside the ZIP.
|
||||
$name = $base;
|
||||
$n = 2;
|
||||
while (isset($usedNames[$name])) {
|
||||
$name = pathinfo($base, PATHINFO_FILENAME).'-'.$n.'.json';
|
||||
$n++;
|
||||
}
|
||||
$usedNames[$name] = true;
|
||||
|
||||
$path = $row->payloadPath();
|
||||
if ($path !== null && Storage::disk('local')->exists($path)) {
|
||||
// addFile streams from disk — payload never enters PHP memory.
|
||||
$abs = Storage::disk('local')->path($path);
|
||||
if (is_string($abs) && $abs !== '' && is_file($abs)) {
|
||||
$zip->addFile($abs, $name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: encode the DB payload (always small — it's a summary).
|
||||
$json = json_encode(
|
||||
$row->fullPayload(),
|
||||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT
|
||||
);
|
||||
$zip->addFromString($name, $json === false ? '{}' : $json);
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
// Stream the temp file in small chunks, then clean up.
|
||||
$fp = fopen($tmp, 'rb');
|
||||
if (is_resource($fp)) {
|
||||
while (! feof($fp)) {
|
||||
echo fread($fp, 65536);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
@unlink($tmp);
|
||||
}, $zipName, [
|
||||
'Content-Type' => 'application/zip',
|
||||
'X-Export-Count' => (string) $total,
|
||||
]);
|
||||
}
|
||||
|
||||
private function page(string $kind)
|
||||
{
|
||||
$agents = $this->isAgentPortal()
|
||||
|
||||
Reference in New Issue
Block a user