Java 如何在HTML表单上绑定文件输入,在后端绑定SpringRestController(无JS)
我有一个SpringRestController,带有自动连接的JpaRepository和后端的H2嵌入式数据库Java 如何在HTML表单上绑定文件输入,在后端绑定SpringRestController(无JS),java,spring-boot,forms,spring-restcontroller,Java,Spring Boot,Forms,Spring Restcontroller,我有一个SpringRestController,带有自动连接的JpaRepository和后端的H2嵌入式数据库 @RestController public class BooksController { @Autowired private BookRepository repository; // POST method will be here } UI是一个带有标记的简单表单 <form class="form-horizo
@RestController
public class BooksController {
@Autowired
private BookRepository repository;
// POST method will be here
}
UI是一个带有
标记的简单表单
<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>
指定XLS文件的路径:
我需要一个方法,我可以从输入表单处理文件。如何将UI输入表单与RestController绑定?是否有专门的libs用于在后端处理XLS文件
主要目标是解析XLS文件并将数据存储在DB单独的列中。解决方案是使用多部分文件作为请求参数,在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();
}
@RequestMapping(value=“/book/upload”,
method=RequestMethod.POST,
consumes=MediaType.MULTIPART\u FORM\u DATA\u VALUE,
products=MediaType.APPLICATION\u JSON\u值)
公共字符串上载(@RequestParam(value=“file”)MultipartFile文件)引发IOException{
HashMap data=ReadExcelUtil.readData(文件);
StringBuilder响应=新建StringBuilder();
data.forEach((字符串键,列表值)->{
response.append(“数据为”).append(键).append(“列:\n”);
value.forEach((String val)->response.append(val.append(“\n”));
});
返回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;
}
}
公共类ReadExcelUtil{
公共静态HashMap readData(多部分文件){
HashMap结果=新建HashMap();
输入流输入流;
试一试{
inputStream=file.getInputStream();
}捕获(IOE异常){
抛出新的运行时异常(e);
}
工作簿=空;
字符串扩展名=FilenameUtils.getExtension(file.getOriginalFilename());
开关(扩展名.toLowerCase()){
案例“xls”:{
试一试{
工作簿=新的HSSF工作簿(inputStream);
}捕获(IOE异常){
抛出新的运行时异常(e);
}
打破
}
案例“xlsx”:{
试一试{
工作簿=新XSSF工作簿(inputStream);
}捕获(IOE异常){
抛出新的运行时异常(e);
}
打破
}
违约:
抛出新的RuntimeException(“不支持的文件扩展名。有效的是XLS和XLSX。”);
}
工作表=工作簿。getSheetAt(0);
对于(int i=0;i{
row.forEach((单元格)->{
final int rowIndex=row.getRowNum();
if(cellIndex==cell.getColumnIndex()){
如果(行索引==0){
键[0]=getCellValue(单元格);
}否则{
value.add(getCellValue(cell));
}
}
});
结果.输入(键[0],值);
});
}
返回结果;
}
受保护的静态字符串getCellValue(单元格){
字符串结果=”;
如果(单元格!=null){
开关(cell.getCellType()){
case Cell.Cell\u类型\u布尔值:
结果=String.valueOf(cell.getBooleanCellValue());
打破
case Cell.Cell\u类型\u数值:
结果=String.valueOf(cell.getNumericCellValue());
打破
case Cell.Cell\u类型\u字符串:
结果=cell.getStringCellValue();
打破
case Cell.Cell\u类型\u空白:
打破
case Cell.Cell\u类型\u错误:
打破
}
}
返回结果;
}
}
解决方案是使用多部分文件作为RequestParam,在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();
}
@RequestMapping(value=“/book/upload”,
method=RequestMethod.POST,
consumes=MediaType.MULTIPART\u FORM\u DATA\u VALUE,
products=MediaType.APPLICATION\u JSON\u值)
公共字符串上载(@RequestParam(value=“file”)MultipartFile文件)引发IOException{
HashMap data=ReadExcelUtil.readData(文件);
StringBuilder响应=新建StringBuilder();
data.forEach((字符串键,列表值)->{
response.append(“数据为”).append(键).append(“列:\n”);
value.forEach((String val)->response.append(val.append(“\n”));
});
返回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;
}
}
公共类ReadExcelUtil{
公共静态HashMap readData(多部分文件){
HashMap结果=新建HashMap();
输入流输入流;
试一试{
inputStream=file.getInputStream();
}捕获(IOE异常){
抛出新的运行时异常(e);
}
工作簿=空;
字符串扩展名=FilenameUtils.getExtension(file.getOriginalFilename());
开关(扩展名.toLowerCase()){
案例“xls”:{
试一试{
工作簿=新的HSSF工作簿(inputStream);
}捕获(IOE异常){
抛出新的运行时异常(e);
}
打破
}