最近做了一个导入excel的相关需求,不难。但是测试过程中,发现导入文件格式的不确定性,需要校验过滤。
*即使提供了导入模板的下载,但是你不能确保用户在导入的时候,不会对模板本身做修改。
我个人觉得这种校验实属没必要,因为在提供的模板中,应该限制哪些地方可以编辑,哪些不可以,而不是在后台代码中做这种验证。不过从代码逻辑的角度来讲,也不妨来看看,这种校验该如何处理。
/**
* 检验导入Excel的格式
* @param excel
* @return
* @throws Exception
*/
public String checkExcelPattern(MultipartFile excel) throws IOException{
if(excel == null || excel.isEmpty()){
throw new BusinessException("导入文件不能为空!");
}
//用于拼接校验结果
StringBuilder builder = new StringBuilder();
if((excel.getSize()/1048576)>2){
builder.append("上传文件仅支持2M以内的Excel文件;");
}
//校验文件格式,必须为excel文件
String fileName = excel.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
if (!"xlsx".equals(suffix)) {
builder.append("导入文件只支持xlsx类型后缀;");
}
//校验文件表头
InputStream fin = excel.getInputStream();
XSSFWorkbook wb = new XSSFWorkbook(fin);
String[] columnName = {"学号*", "姓名*", "性别*", "年龄"};
Sheet sheet = wb.getSheetAt(0);
Row row = sheet.getRow(0);
if (row != null && row.getLastCellNum() >= columnName.length) {
int lastCellNum = row.getLastCellNum();
for (int idx = 0; idx < lastCellNum; idx++) {
String value = getCellValue(row.getCell(idx)).trim();
if (idx < 4) {
if (StringUtils.isBlank(value) || !columnName[idx].equals(value)) {
builder.append("第" + (idx + 1) + "列表头应为" + columnName[idx] + ";");
}
} else {
if (idx == 4) {
builder.append("导入文件只应该有4列;");
}
}
}
} else {
builder.append("上传文件首行不能为空,且应与模板文件表头保持一致;");
}
if(builder.length()>0){
builder.setCharAt(builder.length()-1, '!');
}
return builder.toString();
}
/**
* 获取cell值
* @param cell
* @return
*/
private String getCellValue(Cell cell) {
String cellValue = "";
// 以下是判断数据的类型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: // 数字
if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
cellValue = sdf.format(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell.getNumericCellValue())).toString();
} else {
DataFormatter dataFormatter = new DataFormatter();
cellValue = dataFormatter.formatCellValue(cell);
}
break;
case Cell.CELL_TYPE_STRING: // 字符串
cellValue = cell.getStringCellValue();
break;
case Cell.CELL_TYPE_BOOLEAN: // Boolean
cellValue = cell.getBooleanCellValue() + "";
break;
case Cell.CELL_TYPE_FORMULA: // 公式
cellValue = cell.getCellFormula() + "";
break;
case Cell.CELL_TYPE_BLANK: // 空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: // 故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
上述代码校验了文件类型、大小和第一列表头。