# s-file 生产部署 / 上线说明 > 适用版本:2026-09-14(含用户启停/注销、机构账号查询、手机号查记录、机构上传配置、禁用踢下线黑名单) > 构建产物:`target/s-file.jar`(Spring Boot 可执行 fat jar,需 JDK 8) --- ## 0. 上线前必须处理(阻断项) ### 0.1 替换 spire.pdf 占位 jar ⚠️ 本机构开发机的 `~/.m2/repository/e-iceblue/spire.pdf/3.7.4/` 中目前安装的是**编译级 stub(空实现)jar**——它能保证编译打包通过,但 **PDF 盖章功能(`PdfUtils.pdfStampPerPage`)运行时必然失败**。 上线前必须: 1. 从公司私服获取真实的 `spire.pdf-3.7.4.jar`(阿里云与 e-iceblue 官方仓库均无此版本); 2. 覆盖 `~/.m2/repository/e-iceblue/spire.pdf/3.7.4/spire.pdf-3.7.4.jar`(pom 同步覆盖); 3. 重新 `mvn clean package -DskipTests`; 4. 验证:解包 jar 中 `com/spire/pdf/PdfDocument.class` 应为真实实现(stub 版仅 300~500 字节)。 > 若该业务暂时不用 PDF 盖章,可带 stub 上线,但需明确告知团队。 ### 0.2 提供生产配置文件 **仓库内不含任何运行配置**(application.yml 是外置的)。启动时通过 `spring.config.additional-location` 挂载。生产模板如下(按实际环境修改): ```yaml server: port: 8080 spring: application: name: s-file datasource: # 生产为达梦 DM8;驱动 com.dameng.jdbc.driver(pom 已含依赖) url: jdbc:dm://:5236/S_FILE driver-class-name: com.dameng.jdbc.driver username: password: druid: initial-size: 5 min-idle: 5 max-active: 20 validation-query: SELECT 1 redis: # 必须可用:登录缓存 + 禁用/注销踢下线黑名单依赖 Redis host: port: 6379 timeout: 5000 rabbitmq: host: port: 5672 username: password: servlet: multipart: max-file-size: 500MB # 按网盘需求调整 max-request-size: 500MB main: allow-bean-definition-overriding: true mybatis-plus: mapper-locations: classpath*:com/senmesh/**/mapper/*.xml # 必须有,否则自定义 XML 的接口全部报 Invalid bound statement system: code: 1 # 发号器雪花 workerId:键格式 code.snowflake.workid.<本机IP> # 单机部署:直接写死本机 IP 的键;多机部署:每台机器一个键、值必须不同且 0~31 "[code.snowflake.workid.192.168.1.10]": 1 security: jwt: enable: true secret: <上线前必须换成 64 字节以上随机串,勿用文档示例> expiration: 86400 # token 有效期(秒) header: Authorization ignoring: /error,/favicon.ico,/v2/api-docs,/swagger-resources/** login-page: /login superior-only: false # true=仅平台机构用户可登录系统;按部署侧实际选择 use-local: true allow-if-all-abstain-decisions: true oauth2: enable: false anonymous: "" # 匿名白名单按需追加(逗号分隔,如 /file/upload) user: default: password: <新用户初始密码> file: upload-dir: /data/upload # 容器/主机上需存在且可写 storage: type: local # 阿里云 OSS 则改 ali 并补齐 oss 配置 transfer: location: "1" # 内网侧 "1",外网侧 "2" —— 两侧必须相反! send-dir: /data/transfer/send receive-dir: /data/transfer/receive unpack-risk-check: false dify: risk: rule: api-key: <真实key或占位> scan: api-key: <真实key或占位> # 必填(可为占位),否则启动失败 rabbitmq: custom: topic-exchange-name: s-file-topic delayed-exchange-name: s-file-delayed broadcast-id: s-file-broadcast swagger: enable: false # 生产必须 false ``` ### 0.3 数据库变更 - **已有生产库**:执行 `db/upgrade-20260914-upload-config.sql`(达梦执行「1. MySQL / 达梦 DM8」一节,建 `x_upload_config` 表)。其余本次功能无表结构变更。 - **全新库**:先执行 `db/init-table.sql`(达梦按 MySQL 兼容模式)+ `db/init-data.sql`(平台、平台机构、admin 账号、文件种类字典)。 - 执行后验证:`select count(*) from x_upload_config;` 无报错即建表成功(0 行为正常,未配置的机构走默认策略)。 ### 0.4 目录与权限 ``` mkdir -p /data/upload /data/transfer/send /data/transfer/receive chown -R <运行用户> /data ``` 外网侧与内网侧通过 `file.transfer.location` 区分,`send-dir`/`receive-dir` 指向各自的摆渡目录(网闸/摆渡盘)。 --- ## 1. 启动方式 ### 1.1 裸机 / 虚拟机(JDK 8) ```bash # 需 JDK 1.8(java -version 确认) java -Xms1g -Xmx2g \ -Dspring.config.additional-location=file:/opt/sfile/config/application.yml \ -jar /opt/sfile/s-file.jar \ > /opt/sfile/logs/stdout.log 2>&1 & ``` 多节点时按节点 IP 配置不同的 `code.snowflake.workid.`(可用启动参数 `-DCODE_SNOWFLAKE_WORKID_=` 环境变量方式,`_` 映射 `.`)。 ### 1.2 Docker ```bash # 构建(context 内需 s-file.jar 与 Dockerfile,Dockerfile 在 src/main/resources/) cp target/s-file.jar / && docker build -t s-file:<版本> docker run -d --name sfile-app --restart unless-stopped -p 8080:8080 \ -v /opt/sfile/config/application.yml:/config/application.yml:ro \ -v /data/upload:/data/upload \ -v /data/transfer/send:/data/transfer/send \ -v /data/transfer/receive:/data/transfer/receive \ -e SPRING_CONFIG_ADDITIONAL_LOCATION=file:/config/application.yml \ -e CODE_SNOWFLAKE_WORKID_<容器IP大写下划线>=1 \ s-file:<版本> ``` > 注意:基础镜像 `freshworks/oraclejdk8` 为 amd64,arm64 主机需 `--platform linux/amd64`;workerId 键里的 IP 用容器固定 IP(自定义网络 `--ip`),容器重建 IP 不变。 --- ## 2. 前端发布 ```bash cd senmesh-zc-legacy bun install bun run build # 产出 dist/(.env.production 已带 VITE_APP_TITLE 引号修复,规避 Bun env 解析 bug) ``` - `dist/` 交由 nginx 托管; - nginx 需将 `/api` 反代到后端并**去掉 `/api` 前缀**(与 vite dev 代理行为一致): ```nginx location /api/ { proxy_pass http://<后端IP>:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; client_max_body_size 500m; # 与后端 multipart 上限匹配 } ``` - `.env.production` 当前值:`VITE_API_URL=`(空,走同域 /api)、`VITE_INIT_PASSWORD`(前端判断初始密码强制改密用)——如有调整需重新 build。 --- ## 3. 本次版本功能与数据依赖清单(验收用) | 功能 | 依赖 | 验收方法 | |---|---|---| | 用户启用/禁用/注销(管理员) | DB `uc_user.enabled/status`;**Redis**(禁用踢下线黑名单) | 禁用后该用户已登录 token 立即失效(302/401),重新登录被拒 | | 机构管理员启停本机构用户 | 无额外依赖 | 机构管理员可启停本机构用户;跨机构返回「只能操作本机构的用户」 | | 机构账号查询(超管) | 新增只读查询 | 管理后台-机构账号页正常出列表与筛选 | | 按手机号查上传/发送/接收记录 | 无额外依赖 | 输入手机号出记录;发送/接收方向由部署侧 `file.transfer.location` 决定 | | 机构上传配置 | 新表 `x_upload_config` | 管理后台-上传配置保存后,该机构网盘上传立即按策略拦截 | | 禁用踢下线 | Redis key `user:disabled:{userId}` | `redis-cli keys 'user:disabled:*'` 可见禁用标记 | --- ## 4. 上线步骤建议 1. 生产库执行 0.3 升级 SQL(执行前备份); 2. 替换真实 spire.pdf jar 并重新打包(0.1),核对 jar 时间戳; 3. 准备 application.yml(0.2 模板),**核对 JWT secret 已更换、dify api-key 已填、swagger.enable=false**; 4. 创建 /data 目录,确定内外网 location; 5. 部署后端(1.1 或 1.2),观察启动日志出现 `Started SFileApplication`; 6. 构建并发布前端(2),nginx reload; 7. 验收第 3 节清单(至少:admin 登录、上传一个非白名单文件被拒、禁用一个测试用户并确认其会话失效、记录查询出数据); 8. 观察日志无 `ERROR`,Redis 中 `user:disabled:*` 与登录缓存键正常。 ## 5. 回滚 - 后端:保留上一版 jar/镜像,停新启旧即可(本次无破坏性 DDL/DML,`x_upload_config` 留存不影响旧版本运行); - 前端:nginx 指回上一版 dist 目录; - 数据库:无需回滚(仅新增表)。