org.apache.commons commons-csv 1.7 commons-fileupload commons-fileupload

java-CSV工具类

@Data
public class CsvImportUtil {
    //上传文件的路径
    private final static URL PATH = Thread.currentThread().getContextClassLoader().getResource("");
    public static File uploadFile(MultipartFile multipartFile) {
        // 获 取上传 路径
        String path = PATH.getPath() + multipartFile.getOriginalFilename();
        try {
            // 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
            File file = new File(path);
            // 此抽象路径名表示的文件或目录是否存在
            if (!file.getParentFile().exists()) {
                // 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
                file.getParentFile().mkdirs();
            // 转换为一般file 文件
            multipartFile.transferTo(file);
            return file;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
     * @return List<List<String>>
     * @Description 读取CSV文件的内容(不含表头)
     * @Param filePath 文件存储路径,colNum 列数
    public static List<List<String>> readCSV(String filePath, int colNum) {
        BufferedReader bufferedReader = null;
        InputStreamReader inputStreamReader = null;
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(filePath);
            inputStreamReader = new InputStreamReader(fileInputStream);
            bufferedReader = new BufferedReader(inputStreamReader);
            CSVParser parser = CSVFormat.DEFAULT.parse(bufferedReader);
            //  表内容集合,外层 List为行的集合,内层 List为字段集合
            List<List<String>> values = new ArrayList<>();
            int rowIndex = 0;
            // 读取文件每行内容
            for (CSVRecord record : parser.getRecords()) {
                //  跳过表头
                if (rowIndex == 0) {
                    rowIndex++;
                    continue;
                // 判断下角标是否越界
                if(colNum>record.size()){
                    // 返回空集合
                    return values;
                //  每行的内容
                List<String> value = new ArrayList<>();
                for (int i = 0; i < colNum; i++) {
                    value.add(record.get(i));
                values.add(value);
                rowIndex++;
            return values;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
            if (inputStreamReader != null) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
        return null;

controller 层java类

@Api(value = "后台考勤管理模块")  //Swagger测试文件
@CrossOrigin                    // 关于跨域
@RestController                 // 表明为Controller层
@RequestMapping("/admin/attendance")  // url请求路径
public class AttendanceAdminController {
    @Autowired
    AttendanceService attendanceService;
    @ApiOperation(value = "后台出勤信息Csv批量导入")
    @PostMapping("/csv/import/{month}")
    public R csvImport(
            @ApiParam(name = "month",value = "月份",required = true)
            @PathVariable String month,
            @ApiParam(name = "file", value = "Csv文件",required = true)
            @RequestParam MultipartFile file ){
        // 使用CSV工具类,生成file文件
        File csvFile = CsvImportUtil.uploadFile(file);
        // 将文件内容解析,存入List容器,List<String>为每一行内容的集合,20为CSV文件每行的总列数
        List<List<String>> lists = CsvImportUtil.readCSV(csvFile.getPath(), 20);
        if (lists.size()<1){
            return R.error().message("上传失败").data("errorMsg","文件内容为空或模板不对");
        List<String> errorMsg = attendanceService.csvImport(month,lists);
        // 删 除文件
        csvFile.delete();
        if (errorMsg.size()==0){
            return R.ok().message("文件上传成功");
        return R.error().message("上传失败").data("errorMsg",errorMsg);

后边service层和mapper层代码就不赘述了,因为功能和需求不同,写法就不一样,重点是CSV文件接收和解析,并将数据存入List容器使用。