You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot接口中同名Excel文件多次上传时文件保存异常的解决方案咨询

问题分析与解决方案

首先,咱们先定位问题核心:你每次上传的Excel数据都能成功插入数据库,但同名文件只有第一次能保存到本地。这说明数据库操作的逻辑是正常的,但文件保存环节在重复上传同名文件时出现了异常,而这个异常没有被你及时发现

为什么会出现这个问题?

看你的代码,文件保存部分是这样的:

String destination = "C:\\Users\\anar.memmedov\\Desktop\\app\\" + filePath.getOriginalFilename();
File file1 = new File(destination);
filePath.transferTo(file1);

transferTo方法在目标文件已经存在时,默认会抛出IOException(不同Servlet容器的实现可能略有差异,但大部分都会阻止覆盖已存在的文件)。而你的代码里,这部分逻辑放在了包含数据库操作的try块中:

  • 数据库操作在文件保存之前执行,所以即使后面文件保存失败,数据已经成功插入了数据库。
  • 异常被catch块捕获后,只是打印了栈信息,你没有收到明确的错误反馈,误以为接口正常执行,但实际上文件保存失败了。

解决方案

针对这个问题,有几种常见的处理方式,你可以根据业务需求选择:

1. 生成唯一文件名(推荐,避免文件覆盖)

给每个上传的文件添加唯一标识(比如时间戳、UUID),确保即使文件名相同,保存到本地的路径也不一样。示例代码:

// 获取原文件名
String originalFileName = filePath.getOriginalFilename();
// 生成唯一文件名:时间戳 + 原文件名,避免冲突
String uniqueFileName = System.currentTimeMillis() + "_" + originalFileName;
String destination = "C:\\Users\\anar.memmedov\\Desktop\\app\\" + uniqueFileName;
File file1 = new File(destination);
filePath.transferTo(file1);

2. 强制覆盖已存在的文件

如果你确实需要保留原文件名,并且允许覆盖旧文件,可以在保存前先删除已存在的文件,或者使用Files.copy并指定覆盖选项:

方式A:先删除再保存

String destination = "C:\\Users\\anar.memmedov\\Desktop\\app\\" + filePath.getOriginalFilename();
File file1 = new File(destination);
// 如果文件已存在,先删除
if (file1.exists()) {
    if (!file1.delete()) {
        throw new IOException("无法删除已存在的文件,请检查文件权限或是否被占用");
    }
}
filePath.transferTo(file1);

方式B:使用Files.copy强制覆盖

import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

// ...

String destination = "C:\\Users\\anar.memmedov\\Desktop\\app\\" + filePath.getOriginalFilename();
// 使用Files.copy并指定REPLACE_EXISTING选项强制覆盖
Files.copy(filePath.getInputStream(), Paths.get(destination), StandardCopyOption.REPLACE_EXISTING);

3. 优化异常处理

另外,你当前的异常处理逻辑不够完善,建议在catch块中返回明确的错误响应,而不是只打印栈信息:

catch (IOException e) {
    e.printStackTrace();
    return new ResponseEntity<>(new ErrorResponse("文件保存失败: " + e.getMessage(), 500), HttpStatus.INTERNAL_SERVER_ERROR);
}

额外的代码优化建议

除了文件保存的问题,你的Excel单元格处理逻辑也有潜在问题:

while (cellIterator.hasNext()) {
    Cell currentCell = cellIterator.next();
    if (currentCell.getCellType() == CellType.NUMERIC) {
        phoneNumber = NumberToTextConverter.toText(currentCell.getNumericCellValue());
    } else if (currentCell.getCellType() == CellType.STRING) {
        textMessage = String.valueOf(currentCell.getStringCellValue());
    }
}

这段代码会遍历一行中的所有单元格,最后一个数字单元格会覆盖phoneNumber,最后一个字符串单元格会覆盖textMessage——如果你的Excel是固定列(比如第一列是手机号,第二列是短信内容),建议按列索引来获取单元格,避免意外覆盖:

// 跳过表头行(如果你的Excel有表头的话)
if (currentRow.getRowNum() == 0) {
    continue;
}

// 假设第0列是手机号,第1列是短信内容
Cell phoneCell = currentRow.getCell(0);
if (phoneCell != null && phoneCell.getCellType() == CellType.NUMERIC) {
    phoneNumber = NumberToTextConverter.toText(phoneCell.getNumericCellValue());
}

Cell messageCell = currentRow.getCell(1);
if (messageCell != null && messageCell.getCellType() == CellType.STRING) {
    textMessage = messageCell.getStringCellValue();
}

另外,你用了try-with-resources来包裹InputStream excelFile,这会自动关闭流,所以手动调用excelFile.close()是多余的,可以去掉。

内容的提问来源于stack exchange,提问作者iwritecomeinmymind

火山引擎 最新活动