提交代码

This commit is contained in:
zlwu committed 2025-10-24 23:34:48 +08:00
1 parent e97c97aa0b
commit 1b117de6cf
3 files changed
+1246 -102

No files matched your search

@@ -0,0 +1,300 @@
# 后端文件上传数据丢失问题
**发现日期**: 2025-01-24
**问题模块**: 文件上传/OSS服务
**影响范围**: 所有使用附件上传的业务模块
**严重程度**: ⚠️ 中等(影响用户体验,但有前端兜底)
---
## 问题描述
后端在保存文件时丢失了真实的文件名和扩展名信息,导致前端回显时无法正确识别文件类型。
### 问题表现
从 `/resource/oss/listByIds/{ossIds}` API 返回的数据中:
```javascript
{
ossId: "1981738218223079425",
originalName: "12038a7c-48bd-4978-bcbb-1119a201a6e9", // ❌ UUID,不是用户上传的真实文件名
fileSuffix: "9", // ❌ 数字字符,不是真实扩展名(应该是 jpg/png 等)
fileName: "2025/10/24/aa991fe4d6114995a0562d783cea56139", // ❌ 没有扩展名
url: "/resource/oss/download/1981738218223079425"
}
```
### 期望的数据格式
```javascript
{
ossId: "1981738218223079425",
originalName: "违纪现场照片.jpg", // ✅ 用户上传时的真实文件名
fileSuffix: "jpg", // ✅ 真实的文件扩展名
fileName: "2025/10/24/aa991fe4d6114995a0562d783cea56139.jpg", // ✅ 包含扩展名
url: "/resource/oss/download/1981738218223079425"
}
```
---
## 问题分析
### 可能的原因
1. **文件上传时未保存原始文件名**
- 上传接口 `/resource/oss/upload` 可能未正确提取文件名
- `originalName` 字段被UUID覆盖
2. **扩展名提取错误**
- `fileSuffix` 字段提取逻辑有误
- 从文件路径末尾提取了一个字符(如 `9`、`e`、`d`)而不是真实扩展名
3. **数据库保存逻辑问题**
- `sys_oss` 表中的字段未正确保存
- 可能是某个字段映射错误
### 影响的业务场景
- ✅ **新增上传**:正常工作(文件可以上传)
- ❌ **回显展示**:文件类型识别错误,图片无法正常显示
- ❌ **下载功能**:下载的文件名显示为UUID,用户体验差
- ❌ **文件管理**:管理员无法识别文件内容
---
## 复现步骤
1. 在移动端进入"宿舍卫生检查"模块
2. 点击"录入违纪",上传一张图片(如 `photo.jpg`)
3. 保存违纪记录
4. 刷新页面或重新进入
5. 点击"编辑"查看违纪记录
6. **问题**:附件无法显示为图片,文件名显示为UUID
---
## 调试信息
### 前端上传请求
```javascript
// 调用上传接口
POST /resource/oss/upload
Content-Type: multipart/form-data
// FormData:
file: [Blob] photo.jpg
bizType: "dorm_violation_attachment"
```
### 后端返回(上传成功)
```javascript
{
code: 200,
data: {
ossId: "1981738218223079425",
url: "/resource/oss/download/1981738218223079425",
fileName: "2025/10/24/aa991fe4d6114995a0562d783cea56139" // ⚠️ 缺少扩展名
}
}
```
### 后端返回(回显查询)
```javascript
// GET /resource/oss/listByIds/1981738218223079425
{
code: 200,
data: [{
ossId: "1981738218223079425",
originalName: "12038a7c-48bd-4978-bcbb-1119a201a6e9", // ❌ UUID
fileSuffix: "9", // ❌ 错误
fileName: "2025/10/24/aa991fe4d6114995a0562d783cea56139",
url: "/resource/oss/download/1981738218223079425"
}]
}
```
---
## 建议的修复方案
### 方案1:修复上传接口(推荐)⭐
**修改文件**:`backend/src/main/java/com/ruoyi/resource/controller/SysOssController.java`
**修复点**:
1. 上传时正确提取并保存 `originalName`(用户上传的文件名)
2. 正确提取文件扩展名保存到 `fileSuffix`
3. 保存到OSS的文件名应包含扩展名
```java
@PostMapping("/upload")
public R<SysOss> upload(@RequestParam("file") MultipartFile file,
@RequestParam(required = false) String bizType) {
// 获取原始文件名
String originalFilename = file.getOriginalFilename();
// 提取真实扩展名
String extension = "";
if (originalFilename != null && originalFilename.contains(".")) {
extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
}
// 生成OSS文件名(包含扩展名)
String ossFileName = generateOssFileName() + "." + extension;
// 保存到数据库
SysOss oss = new SysOss();
oss.setOriginalName(originalFilename); // ✅ 保存真实文件名
oss.setFileSuffix(extension); // ✅ 保存真实扩展名
oss.setFileName(ossFileName); // ✅ 包含扩展名的OSS文件名
// ... 其他逻辑
}
```
### 方案2:修复查询接口
**修改文件**:`backend/src/main/java/com/ruoyi/resource/service/impl/SysOssServiceImpl.java`
**修复点**:
1. 从数据库正确读取 `originalName` 和 `fileSuffix`
2. 确保返回的VO类包含正确的字段值
```java
public List<SysOssVo> listByIds(String ossIds) {
// ... 查询逻辑 ...
List<SysOssVo> voList = new ArrayList<>();
for (SysOss oss : ossList) {
SysOssVo vo = new SysOssVo();
vo.setOssId(oss.getOssId());
vo.setOriginalName(oss.getOriginalName()); // ✅ 确保读取正确
vo.setFileSuffix(oss.getFileSuffix()); // ✅ 确保读取正确
vo.setFileName(oss.getFileName());
vo.setUrl(oss.getUrl());
voList.add(vo);
}
return voList;
}
```
### 方案3:数据库表结构检查
**检查表**:`sys_oss`
**需要确认的字段**:
```sql
-- 检查字段定义
SHOW COLUMNS FROM sys_oss LIKE '%name%';
SHOW COLUMNS FROM sys_oss LIKE '%suffix%';
-- 检查数据示例
SELECT oss_id, original_name, file_suffix, file_name
FROM sys_oss
WHERE oss_id = '1981738218223079425';
```
**期望的字段定义**:
- `original_name` VARCHAR(255) - 用户上传的原始文件名
- `file_suffix` VARCHAR(10) - 文件扩展名(jpg/png/pdf等)
- `file_name` VARCHAR(500) - OSS中的文件路径(应包含扩展名)
---
## 临时解决方案(前端兜底)
**已实施**:在 `ViolationRecordDialog.vue` 中添加了兜底逻辑
```javascript
// 检测 fileSuffix 是否为有效扩展名
if (item.fileSuffix && item.fileSuffix.length <= 5 && /^[a-zA-Z]+$/.test(item.fileSuffix)) {
// 使用 fileSuffix
realExtension = item.fileSuffix.toLowerCase();
fileType = this.getFileTypeBySuffix(realExtension);
} else {
// 默认按图片处理(违纪证明材料大概率是图片)
realExtension = 'jpg';
fullFileName = `违纪证明_${timestamp + index}.jpg`;
fileType = 'image/jpeg';
}
```
**局限性**:
- ✅ 可以临时解决图片回显问题
- ❌ 无法恢复真实的文件名
- ❌ 非图片文件可能被错误识别
- ❌ 用户体验不佳
---
## 验证方法
### 1. 后端修复后的验证
**步骤**:
1. 上传一张图片 `test.jpg`
2. 调用 `/resource/oss/listByIds/{ossId}` 查询
3. 检查返回数据:
- `originalName` 应该是 `test.jpg`
- `fileSuffix` 应该是 `jpg`
- `fileName` 应该包含 `.jpg` 扩展名
**期望日志**:
```
违纪记录:原始数据 - originalName=test.jpg, fileSuffix=jpg, fileName=2025/10/24/xxx.jpg
违纪记录:最终文件名=test.jpg, 扩展名=jpg, 文件类型=image/jpeg
```
### 2. 前端验证
**步骤**:
1. 上传图片后编辑违纪记录
2. 检查附件回显是否正常
3. 检查文件名是否正确显示
**期望结果**:
- ✅ 图片正常显示(不是灰白背景)
- ✅ 文件名显示为真实文件名(不是UUID)
- ✅ 下载文件名正确
---
## 相关文件
**后端**:
- `backend/src/main/java/com/ruoyi/resource/controller/SysOssController.java`
- `backend/src/main/java/com/ruoyi/resource/service/impl/SysOssServiceImpl.java`
- `backend/src/main/java/com/ruoyi/resource/domain/vo/SysOssVo.java`
- `backend/src/main/java/com/ruoyi/resource/domain/SysOss.java`
**前端**:
- `mobile/src/pages/xgss/wsjc/components/ViolationRecordDialog.vue`(已添加兜底逻辑)
**数据库**:
- `sys_oss` 表
---
## 优先级和影响
**优先级**: P2(中等)
**影响评估**:
- **用户体验**: ⬇️ 下降(文件名显示为UUID,无法识别内容)
- **功能可用性**: ✅ 正常(有前端兜底,基本功能可用)
- **数据完整性**: ⚠️ 受影响(历史数据无法恢复真实文件名)
**建议处理时间**: 2周内修复
---
**创建时间**: 2025-01-24
**创建人**: Cursor AI
**状态**: 🔴 待修复