How to upload form data along with image in spring boot - java

I am working on a usecase to upload student details along with his image in spring boot. The entity class looks like
below.
public class Student{
private int rollNo;
private String name;
// few more fields
#Lob
private byte[] picture;
// getters setters
}
JSP file
<!DOCTYPE html>
<html>
<head>
<title>Student Registration</title>
</head>
<body>
<form action="save" method="post" enctype="multipart/form-data">
<input type="text" name="rollNo"/>
<input type="text" name="name"/>
<!-- some more fields -->
<input type="file" name="picture"/>
<input type="submit" value="Registration">
</form>
</body>
</html>
How should i handle the form data in my controller method? In a nutshell how to write controller method to handle both form data and image?

the very basic idea could be as follows
#RestController
public class ImageUploadController {
#RequestMapping(value="/upload", method=RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Object> uploadFile(#RequestParam(required=true, value="picture") MultipartFile file, #RequestParam(name = "rollNo") String rollNo, #RequestParam(name = "name") String name) {
}
}

Related

Request method 'POST' not supported. Spring+Thymeleaf

**Hi everyone. I ran into a problem while developing a web application. The saveEmployee method does not work properly and throws the corresponding error. In the project I use Spring-boot + Thymeleaf. I think there is an error in these two files or a problem in the configuration. But so far I haven't found anything.
**
myRestController.java
#Controller
#RequestMapping("/shop")
public class myRestController {
#Autowired
private EmployeeService employeeService;
#GetMapping("/allEmployees")
public String allEmployees(Model model) {
List<Employee> employees = employeeService.getAllEmployees();
model.addAttribute("employeesList", employees);
return "allEmployees";
}
#GetMapping("/allEmployees/{name}")
public String getEmployeeByName(#PathVariable String name, Model model) {
List<Employee> employees = employeeService.findAllByName(name);
model.addAttribute("employeesList", employees);
return "allEmployees";
}
#GetMapping("/newEmployee")
public String addEmployee(Model model) {
Employee employee = new Employee();
model.addAttribute("employee", employee);
return "addNewEmployee";
}
#RequestMapping()
public String saveEmployee(#ModelAttribute("employee") Employee employee){
employeeService.saveEmployee(employee);
return "index";
}
addNewEmployee.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Add Employee</h1>
<form th:method="POST" th:action="#{shop/allEmployees}" th:object="${employee}">
<label for="name">Enter name:</label>
<input type="text" th:field="*{name}" id="name"/>
<br/>
<label for="surname">Enter surname:</label>
<input type="text" th:field="*{surname}" id="surname"/>
<br/>
<label for="department">Enter department:</label>
<input type="text" th:field="*{department}" id="department"/>
<br/>
<label for="salary">Enter salary:</label>
<input type="text" th:field="*{salary}" id="salary"/>
<br/>
<input type="submit" value="Create!">
</form>
<br><br>
</body>
</html>
In your myRestController.java, I am not seeing any #PostMapping defined. In addNewEmployee.html, it appears you are attempting to call shop/allEmployees with a POST rather than the GET method. If your intention is to pass a body or form to the shop/allEmployees endpoint, you may want to consider either changing your #GetMapping to a #PostMapping that accepts a #RequestBody or creating an entirely new #PostMapping that accepts a #RequestBody.

How to get form data in controller when the form that was submitted has the attribute enctype="multipart/form-data"?

I am having some trouble getting form data in my controller when the form in my jsp contains the attribute enctype="multipart/form-data" . The attribute is needed because i am uploading a file. I simplified my code to make it easier to understand but assume I have the following.
My model:
public class EmployeeUpdateForm {
private String name;
private ContactInfo info;
//standard getters and setters
}
public class ContactInfo {
private String streetName;
private MultipartFile image;
//standard getters and setters
}
My controller is
#Controller
public class EmployeeController {
#RequestMapping(value = "/employee", method = RequestMethod.GET)
public ModelAndView showForm() {
//assume this sends you to updateEmployee.jsp
}
#RequestMapping(value = "/submit", method = RequestMethod.POST)
public String submit(#ModelAttribute("EmployeeUpdateForm")EmployeeUpdateForm form ) {
//here I expect form.getInfo().getStreetName() and form.getInfo().getImage() to return something but they are both null values.
}
}
updateEmployee.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
</head>
<body>
<h3>Update Employee Details</h3>
<form:form action="submit" method="post" enctype="multipart/form-data" id="EmployeeUpdateForm" modelAttribute="EmployeeUpdateForm">
<div>
Street Name: <form:input path="info.streetName" />
</div>
<div>
New Image: <form:input type="file" path="info.image"/>
</div>
</form:form>
</body>
</html>
When I submit my form and check the value of form.getInfo().getStreetName() and form.getInfo().getImage() within submit() in my controller, both values are null.
However if I remove method="post" enctype="multipart/form-data" from my form in jsp and also remove <form:input type="file" path="info.image"/> from my jsp and then proceed to submit, if I do form.getyInfo().getStreetName() it returns the value I filled in.
How do I get form data in my controller when the form in my jsp has the attribute method="post" enctype="multipart/form-data"??
A resolver was missing. Adding
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
fixed the issue.

How to forward form data to another host in Spring MVC Controller?

I have a Controller:
#Controller
public class ImageController {
#GetMapping("/upload")
public String uploadImageGet(Model model) {
return "uploadForm";
}
#PostMapping("/upload")
public String uploadImagePost(#ModelAttribute Image image, Model model) throws IOException {
// what should I do here?
return "result";
}
}
An HTML form:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="#" th:action="#{/upload}" th:object="${image}" method="post" enctype="multipart/form-data">
<label for="name">Name:</label><br>
<input type="text" id="name" name="name" value=""><br>
<label for="description">Description:</label><br>
<input type="text" id="description" name="description" value=""><br>
<label for="author">Author:</label><br>
<input type="text" id="author" name="author" value=""><br>
<label for="image">Image:</label><br>
<input type="file" id="image" name="image"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
And a class for storing the form data:
public class Image {
private String name;
private String author;
private String description;
private MultipartFile image;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public MultipartFile getImage() {
return image;
}
public void setImage(MultipartFile image) {
this.image = image;
}
}
I want to send the form data to another host (Spring API), but also display a "Uploaded successfully" response page. Because of that I wanted to handle all that in the controller, but can't figure out how to do this. I was able to find some resources on creating a request manually, but this seems like there must be some simpler way to do this. If I'm approaching it wrong please let me know.
It hardly depends what you mean by:
I want to send the form data to another host (Spring API)
One approach would be to send the Data async with REST to another Spring application or any other application using springs rest template: https://www.baeldung.com/rest-template.
And show the user a succesfull html site.
But if you do it async you should keep in mind that the REST call could fail but you showed the user a successfull page..
My recommendation would be to create an additional REST Endpoint in your spring boot application and send the data from the site with an fetch or ajax call via javascript to it, from where it could be sent to the other spring application

Spring Boot Forms; hiding the path value and showing placeholder

I am having a small issue with Spring Boot forms displaying the information of the path value instead of the placeholder once you get to the editProfile.jsp. I want the input field to look like this;
Edit Profile Page instead of this Wrong Edit Profile. I do not want my users to have to click, select and delete the auto completed value. I want it to show the placeholder only and allow them to overwrite what is shown with ease.
This is the editProfile.jsp
<%--#elvariable id="editProfile" type=""--%>
<form:form method="POST" modelAttribute="editProfile">
<div class="MyForm form-group">
<h1>Edit Profile</h1>
<form:input type="email" class="MyInput" id="email" path="email" placeholder="${editProfile.email}" />
<form:button type="submit" class="from-control">Submit</form:button>
</div>
<div>
<img src="images/reg1.png" alt="picture">
</div>
</form:form>
</body>
</html>
This is the code specified in the Controller
#RequestMapping(value = "edit/{email}", method = RequestMethod.GET)
public String getEditUserData(#PathVariable("email") String email, Model model) {
AccountEntity accountInstance = accountRepo.findByEmail(email);
model.addAttribute("editProfile", accountInstance);
return "editProfile";
}
#RequestMapping(value = "edit/{email}", method = RequestMethod.POST)
public String enterEditUserData(#ModelAttribute("login") AccountEntity accountForm, #PathVariable("email") String email, Model model ) {
AccountEntity accountInstance = accountRepo.findByEmail(email);
accountInstance.setEmail(accountForm.getEmail());
accountRepo.save(accountInstance);
return "redirect:/login";
}
I have figured it out; You have to add a model of a new Entity, so the path variable does not fill in with the instance of the specific path value. Here is the new code, and compare it to the one I sent above.
#RequestMapping(value = "edit/{email}", method = RequestMethod.GET)
public String getEditUserData(#PathVariable("email") String email, Model model) {
AccountEntity accountInstance = accountRepo.findByEmail(email);
model.addAttribute("editProfile2", new AccountEntity());
model.addAttribute("editProfile1", accountInstance);
return "editProfile";
}
<%--#elvariable id="editProfile" type=""--%>
<%--#elvariable id="editProfile2" type=""--%>
<form:form method="POST" modelAttribute="editProfile2">
<div class="grid form-group">
<h1>Edit Profile</h1>
<form:input type="email" class="MyInput" id="email" path="email" placeholder='${editProfile1.email}' />
<form:button type="submit" class="from-control">Submit</form:button>
</div>

Access data from the URL to java using thymeleaf?

I started to working on thymeleaf, so after submitting the form I end up getting this URL:
URL
http://localhost:8080/submit?name=xyz&age=20&dropdown=male
so how should I get the value of individual elements to java controller?
In java part, I should be able to load them into their respective datatypes.
To grab GET parameters (URL parameters), use request.getParameter
String name = request.getParameter("name");
String age = request.getParameter("age");
String dropdown = request.getParameter("dropdown");
Note that these are all strings, if you want other datatypes you will need to parse them and handle any errors.
So, yes later I was able to solve it
Step1Create an HTML plage GetDetails.HTML
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Details</title>
</head>
<body>
<form action="#" th:action="#{PATH OF ACTION}" method="get" th:object="${details}">
<input type="text" name="name" th:field="*{name}"/>
<input type="text" name="age" th:field="*{age}"/>
<select name="option" th:field="*{option}">
<option value="male">male</option>
<option value="female">female</option>
</select>
<input type="submit" value="search"/>
</form>
</body>
</html>
Step2 Create a Model class in java (POJO)
class Details{
private String name;
private int age;
//getters and setters
//constructors
}
NOTE: Class name must be same as the object name given in HTML page
Step3 Controller part in Java
#RequestMapping("/")
public String search(Model model){
model.addAttribute("details", new Details());
return "GetDetails";
}
Step4 REST controller
#GetMapping(value = "PATH OF ACTION")
public List<Details> getAll(#ModelAttribute Details details) {
// Business service
}

Categories

Resources