public function downloadExcel(Request $request)
{
try {
$param = $request->all();
$file = ltrim($param['file_path'] ?? '', '/');
// 路径安全校验
$basePath = realpath(runtime_path());
$realPath = realpath($basePath . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $file));
if (!$realPath || strpos($realPath, $basePath) !== 0 || !is_file($realPath)) {
throw new \RuntimeException('文件不存在或路径非法');
}
// 统一使用UTF-8编码
$downloadName = $param['file'] ?? date('Y-m-d_His');
$encodedName = rawurlencode($downloadName);
// 创建响应
$response = new BinaryFileResponse($realPath);
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
"filename*=UTF-8''{$encodedName}.xlsx"
);
$response->headers->add([
'Cache-Control' => 'private, max-age=600',
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
]);
$response->headers->set('Content-Length', filesize($realPath));
$response->deleteFileAfterSend(true);
return $response;
} catch (\Throwable $e) {
return response()->json([
'code' => 500,
'msg' => '下载失败:' . $e->getMessage(),
], 500);
}
}
HTTP/1.0 200 OK Cache-Control: max-age=600, private Content-Disposition: attachment; filename="filename=UTF-8''_E5_AF_BC_E5_87_BA_20250523153125.xlsx.xlsx"; filename=utf-8''filename%2A%3DUTF-8%27%27%25E5%25AF%25BC%25E5%2587%25BA_20250523153125.xlsx.xlsx Content-Length: 13082 Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Date: Fri, 23 May 2025 07:31:34 GMT Last-Modified: Fri, 23 May 2025 07:31:26 GMT
这种还是需要自己实现,写个watch
用延时队列,下载几分钟之后删除文件
我用的workerman,单开一个worker,然后使用定时器定时清除。当然这个定时器我让他干了好多活,如果就一个活的话单开一个worker有点奢侈:)