Java csv文件上传下载中的相关转换

目录

  • 一. 需求
  • 二. `List`转`List>`
    • 2.1 实体类
    • 2.2 转换
  • 三. 上传csv文件转`List`
    • 3.1 csv文件
    • 3.2 前台
    • 3.3 实体类
    • 3.4 转换
    • 3.5 效果


一. 需求

项目中遇到了两个需求

1.查询数据库,得到List这种数据类型,然后需要将List转换为List>之后,调用共通方法下载CSV数据。
2.前台上传csv文件到后台,后台需要将csv文件处理为List这种数据类型,然后遍历List插入数据库。


二. ListList>

2.1 实体类

  • 在类的内部定义了一个@excludeCSV注解,用于标识指定的属性不进行转换
import lombok.Builder;
import lombok.Data;

import java.lang.annotation.*;

@Data
@Builder
public class Category {

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface excludeCSV {
    }

    private String id;

    @excludeCSV
    private String password;

    private String parentValid;

    private String parentId;

    private String name;

    private String updateTime;
}

2.2 转换

  • 要点就是反射,因为实体类的属性都是private,所以需要使用 .setAccessible(true) 使其强制可访问。
  • 因为不确定List中的类型是什么,因此使用 List
  • 部分属性不需要转换,使用自定义注解@excludeCSV来标识。
import org.springframework.boot.CommandLineRunner;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Field;
import java.util.*;

@Controller
@RequestMapping("/test33")
public class Test33Controller implements CommandLineRunner {
    
    @Override
    public void run(String... args) throws Exception {
		
		// 模拟从数据库查询到的List数据
        List<Category> categoryList = List.of(
                Category.builder().id("1").name("张三").parentId("11").updateTime("2023").build(),
                Category.builder().id("2").name("李四").parentId("22").updateTime("2024").build(),
                Category.builder().id("3").name("王五").parentId("33").updateTime("2025").build()
        );
		
		// 进行转换
        List<List<String>> csvDataList = this.handleData(categoryList);
        System.out.println(csvDataList);
        /*
        	[
        		[1, , 11, 张三, 2023], 
        		[2, , 22, 李四, 2024], 
        		[3, , 33, 王五, 2025]
			]
		*/
    }
	
    public List<List<String>> handleData(List<?> dataList) throws IllegalAccessException {

        List<List<String>> strList = new ArrayList<>();
        List<String> valueList;
        Field[] fields;

        for (Object data : dataList) {

            valueList = new ArrayList<>();
            // 获取所有修饰符的属性
            fields = data.getClass().getDeclaredFields();

            for (Field field : fields) {

                // 如果包含指定的注解,则该csv项目不处理
                if (field.isAnnotationPresent(Category.excludeCSV.class)) {
                    continue;
                }

                // 使该属性强制可访问
                field.setAccessible(true);
                // 获取属性值
                valueList.add(Optional.ofNullable(field.get(data)).orElse("").toString());
            }
            strList.add(valueList);
        }

        return strList;
    }
}

三. 上传csv文件转List

3.1 csv文件

"ID","姓名","年龄","地址"
"1","张三",18,"山东省"
"2","李四",19,"山西省"

3.2 前台

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
    <input type="file" id="csv" accept=".csv" />
    <button id="btn">上传文件button>
body>
<script type="text/javascript" th:src="@{/js/public/jquery-3.6.0.min.js}">script>
<script>

    $(function() {
        bindEvent();
    });

    function bindEvent() {
    
        $("#btn").click(() => {

            const formData = new FormData();
            formData.append("multipartFile", $("#csv").get(0).files[0]);

            $.ajax({
                url: `/test33/fileUpload`,
                type: 'POST',
                processData: false,
                contentType: false,
                data: formData,
                success: function (data, status, xhr) {
                    console.log(data);
                }
            });
        });
    }
script>
html>

3.3 实体类

import lombok.Data;
import org.springframework.web.multipart.MultipartFile;

@Data
public class Test33Form {
	
	// 用来接收前台传入的csv文件
    private MultipartFile multipartFile;
}

3.4 转换

  • 因为上传的不是json数据,因此使用Form接收的时候不需要加@RequestBody
  • 后台接收到的文件类型为MultipartFile,需要将其转换为File后读取其中的内容。
  • 可以使用File.createTempFile()创建临时文件,使用完之后需要删除,否则占用磁盘空间。
  • 可以使用Files.readAllLines()读取全部的文本文件数据。
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.*;

@Controller
@RequestMapping("/test33")
public class Test33Controller {

    private static final String CHARSET = "UTF-8";

    // CSV列的字段名映射
    private Map<Integer, String> csvColumnMap = new HashMap<>(){{
        put(0, "id");
        put(1, "name");
        put(2, "age");
        put(3, "address");
    }};

    @PostMapping("/fileUpload")
    public ResponseEntity<Void> fileUpload(Test33Form form) throws IOException {

        // 获取前台上传的csv
        MultipartFile multipartFile = form.getMultipartFile();

        // 将csv文件临时存储到本地
        String originalFilename = multipartFile.getOriginalFilename();

        // 获取文件名以及文件名的后缀
        String fileName = StringUtils.stripFilenameExtension(originalFilename);
        String filenameExtension = StringUtils.getFilenameExtension(originalFilename);

        // 创建临时文件
        File tempFile = File.createTempFile(fileName, filenameExtension);
        multipartFile.transferTo(tempFile);

        // 指定通过 UTF-8 编码读取CSV中的数据; 如果读取的是日语文件,通常格式为 Shift_JIS
        List<String> csvList = Files.readAllLines(tempFile.toPath(), Charset.forName(CHARSET));
        // 删除csv文件中的第一行的标题
        csvList.remove(0);
        // 删除临时文件
        Files.delete(tempFile.toPath());

        List<Map<String, Object>> csvMapList = new ArrayList<>();
        for (String csvRow : csvList) {

            Map<String, Object> csvMap = new HashMap<>();

            List<String> csvItemList = Arrays.asList(csvRow.split(","));
            for (int i = 0; i < csvItemList.size(); i++) {
                csvMap.put(csvColumnMap.get(i), csvItemList.get(i));
            }

            csvMapList.add(csvMap);
        }

        System.out.println(csvMapList);
        
        // 响应给前台
        return ResponseEntity.noContent().build();
    }
}

3.5 效果

Java csv文件上传下载中的相关转换_第1张图片

你可能感兴趣的:(Java,java)