批量導入業務數據(如樣本信息、患者資料),前端上傳 .xls/.xlsx 文件,後端解析入庫,支持多 Sheet、多數據類型(字符串、數字、日期、布爾)。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<form enctype="multipart/form-data" method="post" action="${ctx}/uploadfile">
<input type="file" name="file" />
<input type="submit" value="提交" />
</form>
避坑:action 勿用 upload 作為路徑,極易與框架內部映射衝突導致 404(作者踩坑一天)。
@Service
public class FileUploadServiceImpl implements IFileUploadService {
@Autowired private IFileUploadDao fileDao;
@Override
public List<String[]> readExcel(String path) {
List<String[]> data = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(path)) {
Workbook wb = WorkbookFactory.create(fis); // 自動識別 2003/2007+
for (int s = 0; s < wb.getNumberOfSheets(); s++) {
Sheet sheet = wb.getSheetAt(s);
for (Row row : sheet) {
if (row.getRowNum() == 0) continue; // 跳過表頭
int cellCount = row.getPhysicalNumberOfCells();
String[] rowData = new String[cellCount - 1]; // 第一列為 ID 標識,不入庫
for (int c = 1; c < cellCount; c++) {
Cell cell = row.getCell(c);
rowData[c - 1] = getCellValueAsString(cell); // 統一轉字符串
}
data.add(rowData);
}
}
} catch (Exception e) { throw new RuntimeException("Excel 解析失敗", e); }
return data;
}
private String getCellValueAsString(Cell cell) {
if (cell == null) return "";
switch (cell.getCellTypeEnum()) {
case STRING: return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell))
return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
return String.valueOf(cell.getNumericCellValue());
case BOOLEAN: return String.valueOf(cell.getBooleanCellValue());
case BLANK: return "";
case FORMULA: return "FORMULA";
case ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
@Override public void save(Object o) { fileDao.save(o); }
}
@RequestMapping("/uploadfile")
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request, ModelMap model) {
String realPath = request.getServletContext().getRealPath("upload");
File target = new File(realPath, file.getOriginalFilename());
target.getParentFile().mkdirs();
file.transferTo(target);
List<String[]> rows = fileUploadService.readExcel(target.getAbsolutePath());
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
for (String[] cols : rows) {
Sample sample = new Sample(
cols[0], // sampleNo
Integer.parseInt(cols[1]), // sampleType
fmt.parse(cols[2]), // createTime
cols[3], // name
cols[4] // pId
);
Patient patient = new Patient(cols[5], cols[6]); // hospitalName, cellPhone
fileUploadService.save(sample);
fileUploadService.save(patient);
}
return "redirect:/yyd";
}
SXSSFWorkbook (POI 3.8+) 或 EasyExcel (Alibaba) 避免 OOM。session.flush() + session.clear(),防止一級緩存撐爆內存。Spring MVC + POI 實現 Excel 導入核心在於:MultipartFile 接收 → WorkbookFactory 通用解析 → 統一轉字符串 → 批量入庫。掌握通用解析邏輯與生產級優化點,即可應對絕大多數批量導入場景。