Unable to upload multiple images - Springboot - image

I'm trying to upload multiple images in Springboot.
Here is my form HTML:
<form th:action="#{${#httpServletRequest.requestURI}}" th:object="${formInput}" method="post" enctype="multipart/form-data" onsubmit="return validate();">
To take in multiple files:
<input type="file" onclick="radioButton()" onchange=" enableSubmit();" id = "fileInput" name="uploadingFiles[]" accept="image/*" multiple/>
Here is my controller:
#RequestMapping(value = "/userProfiles/{userId}/setup/Tool.html", method = RequestMethod.POST)
public void makeIAmVideo(#PathVariable Long userId, HttpServletResponse response, #RequestParam(value = "track_value") int trackNumber, #RequestParam("uploadingFiles") MultipartFile[] uploadingFiles) throws IOException {
UserProfile userProfile = userProfileRepository.findById(userId);
ArrayList<String> photos = new ArrayList<>();
String audioPath= audioPath1;
System.out.println(trackNumber);
for(MultipartFile file : uploadingFiles){
photos.add(file.getName());
}
}
But when I debug it, the photos are not uploaded in the photos array list, it's size stays 0.
Am I doing something wrong?

add these line in your form which contain this input field.
enctype="multipart/form-data"

Related

How to upload and save image in MySQL via SpringBoot JPA

I'm trying to upload and save an image in MySQL with SpringBoot using JPA but unfortunately I'm greeted with this error, can anyone tell me what am I missing ?
Error
Field error in object 'institution' on field 'logo': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile#387c2996]; codes [typeMismatch.institution.logo,typeMismatch.logo,typeMismatch.[Ljava.lang.Byte;,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [institution.logo,logo]; arguments []; default message [logo]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.Byte[]' for property 'logo'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.Byte' for property 'logo[0]': PropertyEditor [org.springframework.beans.propertyeditors.CustomNumberEditor] returned inappropriate value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile']]
pom.xml
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
Entity
#Lob
private Byte[] logo;
controller
#PostMapping("/institutionAddNew")
public String addNewComp(#ModelAttribute("institution") Institution institution, Model model,
HttpSession session,
#RequestParam CommonsMultipartFile fileUpload) throws Exception {
Integer insId = (Integer) session.getAttribute("instId");
Byte[] byteObjects = new Byte[fileUpload.getBytes().length];
int i = 0;
for (byte b : fileUpload.getBytes()){
byteObjects[i++] = b;
}
institution.setLogo(byteObjects);
cs.addNewInstitution(institution);
model.addAttribute("institutionlist", cs.getAllInstitutions(insId));
return "redirect:/showAllInstitutions";
}
Form
<form:form action="/institutionAddNew" method="post" modelAttribute="institution" enctype="multipart/form-data">
<form:input path="instName" />
<input type="file" name="logo" />
<button type="submit" class="btn btn-primary">Submit</button>
</form:form>
The provided information is insufficient to properly diagnose the problem. You need to provide more information.
But I am guessing that, when the jsp file is sending data to your controller, it is sending the file as a MultiPartFile. But your application is trying to cast it to an byte array. That's why your are getting the exception. The problem does not lie withJPA, the exception should happen before the data enters the controller.
You can use an dto object to pass the data to your controller where the file is a Multipartfile object, then you can prepare the entity object with the dto object data. Here you can read the multipartfile and convert it to an byte array and then save it to your database.
Add another InstitutionParam class like
public class InstitutionParam {
private MultipartFile logo;
}
Keep your Institution class same. Your controller should look like
#PostMapping("/institutionAddNew")
public String addNewComp(#ModelAttribute("institution") InstitutionParam institution, Model model,
HttpSession session) throws Exception {
Integer insId = (Integer) session.getAttribute("instId");
MultipartFile fileUpload = institution.getLogo();
Byte[] byteObjects = new Byte[fileUpload.getBytes().length];
int i = 0;
for (byte b : fileUpload.getBytes()){
byteObjects[i++] = b;
}
Institution entity = new Institution();
entity.setLogo(byteObjects);
// save to db
cs.addNewInstitution(institution);
model.addAttribute("institutionlist", cs.getAllInstitutions(insId));
return "redirect:/showAllInstitutions";
}
I've managed to solve it eventually, I had to change the code. I'm sure there are many ways of doing this, not sure if this approached is the best one but it works for me.
Entity
private Integer instId;
private String fileName;
private String fileType;
#Lob
private byte[] image;
public Institution(Integer instId, String instName, String fileName, String fileType, byte[] image) {
super();
this.instId = instId;
this.instName = instName;
this.fileName = fileName;
this.fileType = fileType;
this.image = image;
}
Service
public Institution storeFile(Integer instId, String name, MultipartFile file) throws Exception {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
Institution institution = new Institution(instId, name,fileName, file.getContentType(), file.getBytes());
return comrepos.save(institution);
} catch (IOException ex) {
throw new Exception("Could not store file " + fileName, e);
}
}
controller
#PostMapping("/institutionAddNew")
public String uploadImage(#RequestParam("image") MultipartFile file,
#RequestParam("instName") String name,
#RequestParam("instId") Integer instId) {
try {
iservice.storeFile(instId,name,file);
} catch (Exception e) {
e.printStackTrace();
}
return "redirect:/showAllInstitutions";
}
Form
<form:form action="/institutionAddNew" method="post" modelAttribute="institution" enctype="multipart/form-data">
<form:input path="instName" />
<input type="file" name="logo" />
<button type="submit" class="btn btn-primary">Submit</button>
</form:form>

Unable to save file with other text details from a template, which gives "Required request part 'file' is not present" this error

My Controller
#PostMapping
public String registerUserAccount(#ModelAttribute("user") #Valid User user,
BindingResult result, #RequestParam("file") MultipartFile file) throws IOException{
byte[] pic = file.getBytes();
User imageUser = new User(pic);
userService.save(user);
userService.save(imageUser);
return "redirect:/registration?success";
}
I am saving image from controller and other textual details through service
My template
<form class="login100-form validate-form" th:action="#{/registration}" th:object="${user}" method="post" enctype="multipart/form-data">
//other textual inputs like name address and number
<label for="Profile Picture">Profile Picture</label>
<input type="file" name="file" placeholder="Pofile Picture" th:field="*{pic}">
</div>

how to pass binding result object in RedirectView

I am new to spring and I am trying to redirect to the same page if the form has errors. I am successful redirecting that but the problem is the form has a dynamic drop down and the values are not rendered when I return a model object. or when I do ModelAndView(new RedirectView("lookup")) I am able to render the dropdown values but I am unable to display the error messages.
code: jsp: lookup.jsp
<form:form name="lookupForm" method="POST" action="search.html" enctype="multipart/form-data" >
<div style= "color:red">
<form:errors path="empId" /></br>
<form:errors path="companyName" />
</div>
<form:label path="companyName">Company</form:label>
<select name= "companyList" path="companyName">
<option value="Select">Select</option>
<c:forEach var="element" items="${listCompany}">
<option value="${element.companyName}">${element.companyName}</option>
</c:forEach>
</select>
<form:label path="empId">Employee ID</form:label>
<form:textarea name="empId" path="empId" rows="5" cols="30"/>
<input type="submit" name="search" value="Search"/>
Controller:
#RequestMapping(value = "/lookup", method = RequestMethod.GET)
public ModelAndView lookupFormView(ModelAndView model,BindingResult result) {
List<Employee> listCompany = employeeDAO.getCompany();
Employee newContact = new Employee();
model.addObject("listCompany", listCompany);
model.addObject("command", newContact);
model.setViewName("lookup");
return model;
}
#RequestMapping(value = "/search", params = "search", method = RequestMethod.POST)
public ModelAndView lookupEmployee(HttpServletRequest request,HttpServletResponse response, #ModelAttribute("command") Employee emp,BindingResult result) throws Exception{
empValidator.validate(emp, result);
String lookupEmpId = null;
if (result.hasErrors()) {
return new ModelAndView(new RedirectView("lookup"));
//return new ModelAndView("lookup");
}
else{
-----
if i use this return new ModelAndView(new RedirectView("lookup")); its redirecting to lookup.jsp ,rendering the drop down valus but the error messages are not getting displayed.
if i use this return new ModelAndView("lookup"); its redirecting to lookup.jsp ,errors are displayed but the dynamic dropdown values are not rendered.
Please help me in finding which part of my code is wrong or Is their a way to display error messages and render dynamic dropdown values
Just return the view name and set the error message in the Model itself. Simply check the error message in the JSP if found then show it.
sample code:
#RequestMapping(value = "/search", params = "search", method = RequestMethod.POST)
public String lookupEmployee(HttpServletRequest request,HttpServletResponse response,
#ModelAttribute("command") Employee emp,BindingResult result) throws Exception{
empValidator.validate(emp, result);
String lookupEmpId = null;
if (result.hasErrors()) {
emp.setErrorMessage("Your error message.");
return "lookup";
}else{
...
return "successPage";
}
}

Spring portlet ajax call, No parameter found

I am trying to build a sample spring portlet, with LR 6.2 GA1.
Below is the source for the same https://docs.google.com/file/d/0By1kU5o_jlrublhUNXIxQ24wODQ/edit
On the ajax the parameters are not being fetched.The parameters always remain blank.
#Controller(value = "ProjectSearch")
#RequestMapping("VIEW")
public class ProjectSearch {
Log log_ = LogFactoryUtil.getLog(ProjectSearch.class);
#RenderMapping
public String handleRenderRequest(final RenderRequest request,
final RenderResponse response, Model model) {
System.out.println("ProjectSearch.handleRenderRequest()");
return "search_form";
}
#ResourceMapping("getProjectNameSuggestion")
public void getNameSuggestion(ResourceRequest request,
ResourceResponse response) throws IOException {
Map<String, String[]> map = request.getParameterMap();
for (Map.Entry<String, String[]> element : map.entrySet()) {
log_.info(element.getKey());
}
String entityName = ParamUtil.getString(request, "query");
log_.info("Entity name==>" + entityName);
}
}
#RenderMapping
public String handleRenderRequest(final RenderRequest request,
final RenderResponse response, Model model) {
System.out.println("ProjectSearch.handleRenderRequest()");
return "search_form";
}
#ResourceMapping("getProjectNameSuggestion")
public void getNameSuggestion(ResourceRequest request,
ResourceResponse response) throws IOException {
Map<String, String[]> map = request.getParameterMap();
for (Map.Entry<String, String[]> element : map.entrySet()) {
log_.info(element.getKey());
}
String entityName = ParamUtil.getString(request, "query");
log_.info("Entity name==>" + entityName);
}
}
Output-->05:23:24,148 INFO [http-bio-8080-exec-119][ProjectSearch:41] Entity name==>
Could any body tell me what is that I am doing wrong??
Solution:
Configure Requires Name Spaced Parameters to false in liferay-portlet.xml
Now need to do require Name spaced parameters to false then only form data is mapped in Action Request and Render Request. And also form data will be binding to model object or command object.
The following is configuration we need to do in liferay-portlet.xml file
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Required Name Space Parameter Behavior in Liferay
Liferay 6.2 we have to append portlet Name space for every name of input element i.e. form input elements or request parameters names otherwise portlet action class ignore the parameters which does not have portlet name space to names.
Scenario
Jsp page
In the following form we are not appending portlet name space to form input element names.
<portlet:actionURL var="addEmployeeActionURL" name="addEmployee">
<portlet:param name="<%=ActionRequest.ACTION_NAME%>" value="addEmployee"/>
</portlet:actionURL>
<form action="<%=addEmployeeActionURL%>" name="emplyeeForm" method="POST">
Employee Name<br/>
<input type="text" name="employeeName" id="employeeName"/><br/>
Employee Address<br/>
<input type="text" name="employeeAddress" id="employeeName"/><br/>
<input type="submit" name="addEmployee" id="addEmployee" value="Add Employee"/>
</form>
Portlet Class Action Method
public class EmplyeePortletAction extends MVCPortlet {
public void addEmployee(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
String employeeName=ParamUtil.getString(actionRequest,"employeeName");
String employeeAddress=ParamUtil.getString(actionRequest,"employeeAddress");
}
}
In above case employeeName and employeeAddress form input data not accessible in portlet class action .The form elements name are not appended with portlet name space such scenarios portlet class ignore those request parameters or form inputs
Solution:1
Need to append tag to every input element name.
Jsp page
<portlet:actionURL var="addEmployeeActionURL" name="addEmployee">
<portlet:param name="<%=ActionRequest.ACTION_NAME%>" value="addEmployee"/>
<portlet:param name="requestParam" value=" requestParamValue"/>
</portlet:actionURL>
<form action="<%=addEmployeeActionURL%>" name="emplyeeForm" method="POST">
Employee Name<br/>
<input type="text" name="<portlet:namespace/>employeeName" id="<portlet:namespace/>employeeName"/><br/>
Employee Address<br/>
<input type="text" name="<portlet:namespace/>employeeAddress" id="<portlet:namespace/>employeeName"/><br/>
<input type="submit" name="addEmployee" id="addEmployee" value="Add Employee"/>
</form>
Portlet Class Action Method
public class EmplyeePortletAction extends MVCPortlet {
public void addEmployee(ActionRequest actionRequest,
ActionResponse actionResponse) throws IOException, PortletException {
String employeeName=ParamUtil.getString(actionRequest,"employeeName");
String employeeAddress=ParamUtil.getString(actionRequest,"employeeAddress");
String requestParamValue=ParamUtil.getString(actionRequest,"requestParam");
}
}
Solution:2
We can make it false to following tag value in liferay-portlet.xml file
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Solution:3
We can use alloy tag library form tags. When we use AUI tags it will append portlet name space to each input element name.
Jsp page
<%# taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<aui:input type="text" name="employeeAddress" id="employeeName"/><br/>
<aui:input type="submit" name="addEmployee" id="addEmployee" value="Add Employee"/
<input type="text" name="<portlet:namespace/>employeeAddress" id="<portlet:namespace/>employeeName"/>
Is same As
<aui:input type="text" name="employeeAddress" id="employeeName"/>
http://www.liferaysavvy.com/2013/12/liferay-spring-portlet.html
http://www.liferaysavvy.com/2014/04/liferay-mvc-portlet-development.html

Spring HTTP Status 400 - The request sent by the client was syntactically incorrect

I have a form which a user is to use to upload a file to a local drive and also persist some data to the database. But this error message has come up which I would like to know how to deal with it.
HTTP Status 400 - The request sent by the client was syntactically incorrect.
The controller
#RequestMapping(value = "/main/user/setter/addpage", method =
RequestMethod.POST, params = "save")
public String saveProcess(#ModelAttribute("module") Module module,
#RequestParam("userId") Integer userId,
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
BindingResult result, HttpSession session) {
if (result.hasErrors()) {
return "redirect:/main/user/setter/settingpage";
}
else
if(module != null){
try {
MultipartFile filea = module.getFileData();
InputStream inputStream = null;
OutputStream outputStream = null;
if (filea.getSize() > 0) {
inputStream = filea.getInputStream();
outputStream = new FileOutputStream("C:\\Test\\"
+ filea.getOriginalFilename());
System.out.println("Uploaded File Name");
System.out.println(filea.getOriginalFilename());
int readBytes = 0;
byte[] buffer = new byte[8192];
while ((readBytes = inputStream.read(buffer, 0, 8192)) !=
-1) {
outputStream.write(buffer, 0, readBytes);
}
outputStream.close();
inputStream.close();
session.setAttribute("success", "File Uploaded");
session.setAttribute("uploadFile", "C:\\Test\\"
+ filea.getOriginalFilename());
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Delegate to service
moduleService.add(userId, module);
return "redirect:/main/user/setter/settingpage";
}
The form itself
<c:url var="processUrl" value="/main/user/setter/addpage?userId=2" />
<form:form modelAttribute="module" method="POST" action="${processUrl}" name="module"
enctype="multipart/form-data">
<form:label path="fileName">Document Title:</form:label>
<form:input path="fileName" name="name"/><br/>
<form:label path="documentPath">Coursework Sample:</form:label>
<form:input path="documentPath" type="file" name="file" id="file" size="43.9"/><br/>
<form:label path="liveDate">Live Date:</form:label>
<form:input path="liveDate"/><br/>
<input type="submit" name="save" value="Save" id="save"/>
<input type="submit" name="send" value="Send" id="send"/>
</form:form>
I'm trying to save the form first the I will use a separate method to send it.
Your method is declared as such:
public String saveProcess(#ModelAttribute("module") Module module,
#RequestParam("userId") Integer userId,
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
BindingResult result, HttpSession session) ...
Assuming that you are trying to apply the BindingResult to the Module instance, you need to change the method definition so that the BindingResult comes right after the Module instance.
public String saveProcess(#ModelAttribute("module") Module module,
BindingResult result,
#RequestParam("userId") Integer userId,
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
HttpSession session) ...
See the reference for more details
The Errors or BindingResult parameters have to follow the model object
that is being bound immediately as the method signature might have
more that one model object and Spring will create a separate
BindingResult instance for each of them [...]
See here.
The error HTTP Status 400 - The request sent by the client was syntactically incorrect. can come from a missing multipartResolver in the context (servlet-context.xml)
`<beans:bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />`
For more info, see the replies from SpringMVC-FileUpload - The request sent by the client was syntactically incorrect

Resources