request->get('path', '')); if ($path === '' || str_contains($path, '..')) { return json(['code' => 400, 'msg' => '非法路径', 'data' => []]); } if (!str_starts_with($path, '/uploads/')) { return json(['code' => 400, 'msg' => '仅允许 /uploads/ 下的文件', 'data' => []]); } $rel = ltrim($path, '/'); $abs = public_path() . str_replace('/', DIRECTORY_SEPARATOR, $rel); $uploadsRoot = realpath(public_path() . 'uploads'); $realFile = realpath($abs); if ($uploadsRoot === false || $realFile === false) { return json(['code' => 404, 'msg' => '文件不存在', 'data' => []]); } if (!str_starts_with($realFile, $uploadsRoot . DIRECTORY_SEPARATOR)) { return json(['code' => 404, 'msg' => '文件不存在', 'data' => []]); } if (!is_file($realFile)) { return json(['code' => 404, 'msg' => '文件不存在', 'data' => []]); } $ext = strtolower(pathinfo($realFile, PATHINFO_EXTENSION)); $mime = match ($ext) { 'jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'webp' => 'image/webp', 'gif' => 'image/gif', default => 'application/octet-stream', }; // 使用 File 响应:输出前清理 output buffer,避免调试输出污染二进制;并设置 Content-Transfer-Encoding 等 return download($realFile, basename($realFile), false, 300) ->mimeType($mime) ->force(false); } }