Raise report upload request size limits

- Configure NestJS with an explicit JSON and urlencoded body parser limit controlled by API_BODY_LIMIT.

- Set the default API body limit to 100mb for report HTML, key frames, template images, and Data URL file uploads.

- Add a matching Nginx client_max_body_size 100m limit so Docker web proxy no longer rejects large report saves first.

- Document the new request body limit in README, deployment docs, progress notes, environment example, and AGENTS context.

- Rebuild and verify Docker web/api with a large report save through the Nginx /api proxy.
This commit is contained in:
2026-05-02 03:29:46 +08:00
parent 285dbd2023
commit 2a86d9f5e4
8 changed files with 16 additions and 3 deletions

View File

@@ -1,5 +1,6 @@
# Backend API development defaults. # Backend API development defaults.
API_PORT=3100 API_PORT=3100
API_BODY_LIMIT="100mb"
CORS_ORIGIN="http://localhost:3001,http://localhost:4002" CORS_ORIGIN="http://localhost:3001,http://localhost:4002"
DATABASE_URL="postgresql://surclaw:surclaw_dev_password@localhost:5433/surclaw?schema=public" DATABASE_URL="postgresql://surclaw:surclaw_dev_password@localhost:5433/surclaw?schema=public"
SESSION_SECRET="change-me-in-production" SESSION_SECRET="change-me-in-production"

View File

@@ -307,6 +307,8 @@ npm run test:e2e
后端第一阶段骨架。当前已实现健康检查、认证接口、报告 API、报告媒体关系、模板 API、字段库 API、用户/部门 API、设置 API、通用文件/签名文件 API、AI 代理、讯飞语音代理、PrismaService 和权限策略前端登录、报告、模板、字段库、模板图片资源、用户管理、系统设置、签名上传、AI 对话和语音听写已接入后端接口/代理。新增后端功能时优先按模块拆分:`auth``reports``templates``library``users``files``settings``ai``speech` 后端第一阶段骨架。当前已实现健康检查、认证接口、报告 API、报告媒体关系、模板 API、字段库 API、用户/部门 API、设置 API、通用文件/签名文件 API、AI 代理、讯飞语音代理、PrismaService 和权限策略前端登录、报告、模板、字段库、模板图片资源、用户管理、系统设置、签名上传、AI 对话和语音听写已接入后端接口/代理。新增后端功能时优先按模块拆分:`auth``reports``templates``library``users``files``settings``ai``speech`
API 默认 JSON/urlencoded 请求体上限为 `100mb`,由 `API_BODY_LIMIT` 控制Nginx 同步配置了 `client_max_body_size 100m`,用于承载迁移期报告 HTML、图片/关键帧和通用文件 Data URL 上传。
### `server/prisma/schema.prisma` ### `server/prisma/schema.prisma`
PostgreSQL 数据模型。当前覆盖 `Tenant``Department``User``UserSession``AppSession``Report``ReportMedia``ReportHistory``Template`、模板部门授权、`FileResource``SystemSetting``AuditLog`。Prisma 7 连接配置在根目录 `prisma.config.ts` 中。 PostgreSQL 数据模型。当前覆盖 `Tenant``Department``User``UserSession``AppSession``Report``ReportMedia``ReportHistory``Template`、模板部门授权、`FileResource``SystemSetting``AuditLog`。Prisma 7 连接配置在根目录 `prisma.config.ts` 中。

View File

@@ -121,6 +121,7 @@ cp .env.example .env.local
当前环境变量: 当前环境变量:
- `API_PORT`NestJS API 监听端口,本地直接运行默认 `3100`Docker Compose 暴露到宿主机的默认端口是 `3002` - `API_PORT`NestJS API 监听端口,本地直接运行默认 `3100`Docker Compose 暴露到宿主机的默认端口是 `3002`
- `API_BODY_LIMIT`NestJS JSON/urlencoded 请求体上限,默认 `100mb`,用于报告 HTML、图片/关键帧和文件 Data URL 上传。
- `CORS_ORIGIN`:允许携带 Cookie 访问 API 的前端来源。 - `CORS_ORIGIN`:允许携带 Cookie 访问 API 的前端来源。
- `DATABASE_URL`PostgreSQL 连接串。Docker Compose 暴露到宿主机的默认端口是 `5433`,容器内部仍使用 `db:5432` - `DATABASE_URL`PostgreSQL 连接串。Docker Compose 暴露到宿主机的默认端口是 `5433`,容器内部仍使用 `db:5432`
- `SESSION_SECRET`:后端 Session Cookie 签名密钥,生产环境必须替换。 - `SESSION_SECRET`:后端 Session Cookie 签名密钥,生产环境必须替换。
@@ -237,7 +238,7 @@ docker-compose down
- `web` 服务使用 Nginx 托管前端 `dist/` - `web` 服务使用 Nginx 托管前端 `dist/`
- `api` 服务运行 NestJS 后端,并把上传文件目录挂载到 `uploads_data` volume。 - `api` 服务运行 NestJS 后端,并把上传文件目录挂载到 `uploads_data` volume。
- `db` 服务运行 PostgreSQL 16。 - `db` 服务运行 PostgreSQL 16。
- `nginx.conf` 已配置 SPA 路由回退`/api` 反向代理。 - `nginx.conf` 已配置 SPA 路由回退`/api` 反向代理`100m` 请求体上限
- `nginx.conf` 已支持 `/api/speech/iat` WebSocket upgrade。 - `nginx.conf` 已支持 `/api/speech/iat` WebSocket upgrade。
## 当前限制 ## 当前限制

View File

@@ -20,6 +20,7 @@ services:
restart: unless-stopped restart: unless-stopped
environment: environment:
API_PORT: 3100 API_PORT: 3100
API_BODY_LIMIT: 100mb
CORS_ORIGIN: http://localhost:4002,http://localhost:3001 CORS_ORIGIN: http://localhost:4002,http://localhost:3001
DATABASE_URL: postgresql://surclaw:surclaw_dev_password@db:5432/surclaw?schema=public DATABASE_URL: postgresql://surclaw:surclaw_dev_password@db:5432/surclaw?schema=public
SESSION_SECRET: change-me-in-production SESSION_SECRET: change-me-in-production

View File

@@ -59,6 +59,7 @@ AI 和语音密钥由后端 Settings API 保存并由代理使用,前端不再
后端新增变量: 后端新增变量:
- `API_PORT`API 监听端口。本地直接运行默认 `3100`Docker Compose 暴露到宿主机的默认端口是 `3002` - `API_PORT`API 监听端口。本地直接运行默认 `3100`Docker Compose 暴露到宿主机的默认端口是 `3002`
- `API_BODY_LIMIT`API JSON/urlencoded 请求体上限,默认 `100mb`。报告正文、关键帧、模板图片和通用文件上传仍可能携带 Data URL调小会导致保存或上传出现 `request entity too large`
- `CORS_ORIGIN`:允许跨域携带 Cookie 的前端来源。 - `CORS_ORIGIN`:允许跨域携带 Cookie 的前端来源。
- `DATABASE_URL`PostgreSQL 连接串。Docker Compose 暴露到宿主机的默认端口是 `5433`,容器内部仍使用 `db:5432` - `DATABASE_URL`PostgreSQL 连接串。Docker Compose 暴露到宿主机的默认端口是 `5433`,容器内部仍使用 `db:5432`
- `SESSION_SECRET`Session Cookie 签名密钥。 - `SESSION_SECRET`Session Cookie 签名密钥。
@@ -87,7 +88,7 @@ docker-compose up -d --build
- `Dockerfile` 使用 Node 构建 `dist/` - `Dockerfile` 使用 Node 构建 `dist/`
- 运行阶段使用 `nginx:alpine` 托管静态文件。 - 运行阶段使用 `nginx:alpine` 托管静态文件。
- `Dockerfile.server` 构建并运行 NestJS API。 - `Dockerfile.server` 构建并运行 NestJS API。
- `nginx.conf` 已配置 SPA 路由回退`/api` 反向代理。 - `nginx.conf` 已配置 SPA 路由回退`/api` 反向代理`100m` 请求体上限
## 部署边界 ## 部署边界

View File

@@ -17,6 +17,7 @@
- 用户管理、部门管理员约束和部门模板授权已优先接入后端 Users/Departments API签名上传和模板图片资源已通过 Files API 写入后端文件资源。 - 用户管理、部门管理员约束和部门模板授权已优先接入后端 Users/Departments API签名上传和模板图片资源已通过 Files API 写入后端文件资源。
- 系统设置、抽帧策略、AI Provider、语音参数和默认模板已优先接入 Settings API只有开发/显式回退模式下才保留本地缓存回退。 - 系统设置、抽帧策略、AI Provider、语音参数和默认模板已优先接入 Settings API只有开发/显式回退模式下才保留本地缓存回退。
- Docker/Nginx 静态部署配置已存在。 - Docker/Nginx 静态部署配置已存在。
- Docker/Nginx 与 NestJS API 已把请求体上限统一到 `100mb`,避免图文报告和文件 Data URL 上传触发默认 413。
- 开发端口已调整为 `3001` - 开发端口已调整为 `3001`
- 已补充 Vitest 测试框架和核心功能单元/组件测试。 - 已补充 Vitest 测试框架和核心功能单元/组件测试。
- 已补充功能盘点,区分真实功能、外部集成、前端演示和预留项。 - 已补充功能盘点,区分真实功能、外部集成、前端演示和预留项。
@@ -77,3 +78,4 @@
| 2026-05-02 | 新增前端组件结构文档梳理页面组件、公共组件、API/Auth/Utils 分层、数据流和大组件拆分边界。 | | 2026-05-02 | 新增前端组件结构文档梳理页面组件、公共组件、API/Auth/Utils 分层、数据流和大组件拆分边界。 |
| 2026-05-02 | 将默认“腹腔镜胆囊切除术报告”后端 seed 与前端默认报告内容对齐,并把系统设置重置改为演示模式恢复出厂设置。 | | 2026-05-02 | 将默认“腹腔镜胆囊切除术报告”后端 seed 与前端默认报告内容对齐,并把系统设置重置改为演示模式恢复出厂设置。 |
| 2026-05-02 | 修正报告草稿后端校验和保存失败提示,补充麦克风启动前置检查。 | | 2026-05-02 | 修正报告草稿后端校验和保存失败提示,补充麦克风启动前置检查。 |
| 2026-05-02 | 增加 Nginx 和 NestJS 请求体上限配置,修复大图文报告保存 `request entity too large`。 |

View File

@@ -6,6 +6,7 @@ map $http_upgrade $connection_upgrade {
server { server {
listen 80; listen 80;
server_name localhost; server_name localhost;
client_max_body_size 100m;
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'; import 'reflect-metadata';
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import cookieParser from 'cookie-parser'; import cookieParser from 'cookie-parser';
import { json, urlencoded } from 'express';
import session from 'express-session'; import session from 'express-session';
import { AppModule } from './app.module.js'; import { AppModule } from './app.module.js';
import { AuthService } from './auth/auth.service.js'; import { AuthService } from './auth/auth.service.js';
@@ -11,10 +12,13 @@ import { attachSpeechProxy } from './speech/speech.gateway.js';
import { SpeechService } from './speech/speech.service.js'; import { SpeechService } from './speech/speech.service.js';
const bootstrap = async () => { const bootstrap = async () => {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule, { bodyParser: false });
const port = Number(process.env.API_PORT ?? 3100); const port = Number(process.env.API_PORT ?? 3100);
const bodyLimit = process.env.API_BODY_LIMIT ?? '100mb';
app.setGlobalPrefix('api'); app.setGlobalPrefix('api');
app.use(json({ limit: bodyLimit }));
app.use(urlencoded({ extended: true, limit: bodyLimit }));
app.useGlobalFilters(new ApiExceptionFilter()); app.useGlobalFilters(new ApiExceptionFilter());
app.enableCors({ app.enableCors({
origin: process.env.CORS_ORIGIN?.split(',') ?? ['http://localhost:3001', 'http://localhost:4002'], origin: process.env.CORS_ORIGIN?.split(',') ?? ['http://localhost:3001', 'http://localhost:4002'],