java - 如何绑定(bind)带有文件输入的 HTML 表单和后端的 Spring RestController(无 JS)

标签 java spring-boot forms spring-restcontroller

我有 Spring RestController,后端有自动连接的 JpaRepository 和 H2 嵌入式数据库。

    @RestController
    public class BooksController {

        @Autowired
        private BookRepository repository;

// POST method will be here
}

UI 是一个简单的表单,带有 <input type="file">标签

<form class="form-horizontal" method="POST" action="/book/upload" enctype="multipart/form-data">
    <div class="form-group">
        <label for="fileInput">Specify path to XLS file:</label>
        <input type="file" name="file" id="fileInput"
               accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel">
        <input type="submit" class="btn btn-primary" value="Upload">
    </div>
</form>

我需要一种可以从输入表单处理文件的方法。如何将 UI 输入表单与 RestController 绑定(bind)?是否有用于在后端处理 XLS 文件的特殊库?

主要目标是解析 XLS 文件并将单独的列数据存储在数据库中。

最佳答案

解决方案是在 RestController 的方法中使用 MultipartFile 作为 RequestParam使用作为 MULTIPART_FORM_DATA_VALUE

@RequestMapping(value = "/book/upload",
        method = RequestMethod.POST,
        consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE)
public String upload(@RequestParam(value = "file") MultipartFile file) throws IOException {

    HashMap<String, List<String>> data = ReadExcelUtil.readData(file);
    StringBuilder response = new StringBuilder();
    data.forEach((String key, List<String> value) -> {
        response.append("Data for ").append(key).append(" column:\n");
        value.forEach((String val) -> response.append(val).append("\n"));
    });
    return response.toString();
}

为了处理 XLS 文件,实现了 ReadExcelUtil。它包含 readData 方法,该方法返回 HashMap,其中键 - 值形成第一行(标题),值 - 当前列的数据列表。

public class ReadExcelUtil {

    public static HashMap<String, List<String>> readData(MultipartFile file) {

        HashMap<String, List<String>> result = new HashMap<>();
        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        Workbook workbook = null;
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        switch (extension.toLowerCase()) {
            case "xls": {
                try {
                    workbook = new HSSFWorkbook(inputStream);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                break;
            }
            case "xlsx": {
                try {
                    workbook = new XSSFWorkbook(inputStream);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                break;
            }
            default:
                throw new RuntimeException("Unsupported file extension. Valid are XLS and XLSX.");
        }

        Sheet sheet = workbook.getSheetAt(0);
        for (int i = 0; i < sheet.getRow(0).getLastCellNum(); i++) {
            final int cellIndex = i;
            final List<String> value = new ArrayList<>();
            final String[] key = {""};
            sheet.forEach((Row row) -> {
                row.forEach((Cell cell) -> {
                    final int rowIndex = row.getRowNum();
                    if (cellIndex == cell.getColumnIndex()) {
                        if (rowIndex == 0) {
                            key[0] = getCellValue(cell);
                        } else {
                            value.add(getCellValue(cell));
                        }
                    }
                });
                result.put(key[0], value);
            });
        }
        return result;
    }

    protected static String getCellValue(Cell cell) {

        String result = "";
        if (cell != null) {
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_BOOLEAN:
                    result = String.valueOf(cell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    result = String.valueOf(cell.getNumericCellValue());
                    break;
                case Cell.CELL_TYPE_STRING:
                    result = cell.getStringCellValue();
                    break;
                case Cell.CELL_TYPE_BLANK:
                    break;
                case Cell.CELL_TYPE_ERROR:
                    break;
            }
        }
        return result;
    }
}

关于java - 如何绑定(bind)带有文件输入的 HTML 表单和后端的 Spring RestController(无 JS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36258953/

相关文章:

java - 从日期对象中提取日期和月份

java - 关于 JDBC 资源和 JDBC 连接池 Glassfish 的一些混淆

java - 考虑在您的配置中定义类型为 'com.gisapp.gisapp.dao.IUserDAO' 的 bean

java - 如何在 Spring Boot 2 和 Activiti 7 中添加 Activiti Spring Boot Starter Basic?

java - 如何为函数中的带注释参数编写mockito

forms - 如何在 codeigniter 表单中同时具有默认值和设置值?

javascript - 从 ajax 调用填充表单

java - 测量 Linux 中的内存使用情况

javascript - HTML 输入标签,无法输入

java - 让一个类实现 java 中未指定的通用接口(interface)