如何将 HTML 表单与文件输入绑定,并在后端绑定 Spring RestController(无 JS)
How to bind HTML form with file input on it and Spring RestController on backend (no JS)
我有 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 绑定?是否有用于在后端处理 XLS 文件的特殊库?
主要目标是解析 XLS 文件并在数据库中存储单独的列数据。
解决方案是使用 MultipartFile 作为 RequestParam, consumes 作为 MULTIPART_FORM_DATA_VALUE在RestController的方法中。
@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 方法,其中 returns 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;
}
}
我有 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 绑定?是否有用于在后端处理 XLS 文件的特殊库?
主要目标是解析 XLS 文件并在数据库中存储单独的列数据。
解决方案是使用 MultipartFile 作为 RequestParam, consumes 作为 MULTIPART_FORM_DATA_VALUE在RestController的方法中。
@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 方法,其中 returns 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;
}
}