批量数据导入
详细说明都写在注释里,看注释就好,核心是处理excel表格,返回值部分没有做任何处理,自己酌情处理
Controller层:FileController类
@RestController
@RequestMapping(value = "fileOpt")
public class FileController {
@Autowired
private FileService fileService;
/**
* 批量导入测试
* @RequestParam括号中的值不能和参数值一样
* testFile(@RequestParam("excel") MultipartFile file) 正确
* testFile(@RequestParam("file") MultipartFile file) 错误
* @param file
* @return
*/
@PostMapping(value = "testFile")
public Result testFile(@RequestParam("excel") MultipartFile file) {
String fileDownloadUri = fileService. testFile(file);
return ResultUtils.success(fileDownloadUri);
}
}
Service
接口:FileService 接口
public interface FileService {
/**
* 上传文件
*
* @param file
* @return
*/
String uploadFile(MultipartFile file);
String testFile(MultipartFile file);
}
实现类 FileServiceImpl实现类
@Slf4j
@Service
public class FileServiceImpl implements FileService {
/**
* 业务层处理excel解析为对象
* 主要解决思路,
* 1.首先判断文件是否为空(file为空,excel文件内容是否为空)
* 2.思考自己需要的数据类型,创建集合(准备封装对象)
* 3.获取输入流,创建Workbook对象,作用:准备进行文件读取操作
* 4.在文件读取之前首先要判断excel文件类型,xls(2003年版本),xlsx(2007,2010,2013版本)
* 5.获取工作表,注意自己是几张工作表(同一个excel文件可能有多张表)
* 6.读取工作表,确认读取的方式,是从第一行开始,还是跳过第一行读取
* 7.关闭流和资源
* @param file
* @return
*/
@Override
public String testFile(MultipartFile file) {
//判断文件是否为空
if(file==null) {return null;}
//获取文件名
String name=file.getOriginalFilename();
//进一步判断文件是否为空(即判断其大小是否为0或其名称是否为null)
long size=file.getSize();
if(name==null || ("").equals(name) && size==0) {return null;}
// 创建list集合,用来封装从excel中获取的数据
ArrayList<ArrayList<String>> listExcel = new ArrayList<>();
try {
//获取输入流,这里可以去看下MultipartFile接口继承了InputStreamSource接口
// 而InputStreamSource接口仅有一个方法getInputStream,返回值是InputStream
// 所以这里可以把file对象通过get方法得到输入流
InputStream in = file.getInputStream();
Workbook workbook = null;
//判断excel版本,获取符合文件的版本
String fileName = file.getOriginalFilename();
if (judegExcelEdition(fileName)) {
workbook = new XSSFWorkbook(in);
} else {
workbook = new HSSFWorkbook(in);
}
//获取第一张工作表,注意,一个excel文件可能有多张表sheet1,sheet2.。。。。。
Sheet sheet = workbook.getSheetAt(0);
//从第二行开始获取 getLastRowNum,从表头开始getPhysicalNumberOfRows
for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
//循环获取工作表的每一行
Row sheetRow = sheet.getRow(i);
// 方法一:把对象封装到list集合里
//循环获取每一列,准确的说是获取某行的某列值,本质上还是某个单元格的值
// 创建list集合,用来存表格中的数据,一行是一个list对象,一列是list对象中存储的一个值
// eg:第一行:{第一列,第二列,第三列,。。。}
ArrayList<String> list = new ArrayList<>();
for (int j = 0; j < sheetRow.getPhysicalNumberOfCells(); j++) { //
//将每一个单元格的值装入列集合
// 这个方法过期了,现在采用替换解决方案
// sheetRow.getCell(j).setCellType(Cell.CELL_TYPE_STRING);
sheetRow.getCell(j).setCellType(CellType.STRING);
list.add(sheetRow.getCell(j).getStringCellValue());
}
//将装有每一列的集合装入大集合
listExcel.add(list);
// 方法二:把值存入到对象中进行封装,要注意listExcel中的泛型要更改为你所需求对象类型
// 封装方法,可以创建对象,用set方法封装,也可以使用全参的构造方法进行封装
// 实现方法:略
//关闭资源
workbook.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
log.info("未找到文件");
} catch (IOException e) {
e.printStackTrace();
log.info("文件上传失败");
}
return null;
}
// 用来是否是xls格式,返回布尔型
private static boolean judegExcelEdition(String fileName){
if (fileName.matches("^.+\\.(?i)(xls)$")){
return false;
}else {
return true;
}
}
}
}