Spring Boot Required request part 'file' is not present - java

I am trying to create a file upload utility and am getting the following error when I click on the submit button. It starts uploading and then suddenly has this error:
There was an unexpected error (type=Bad Request, status=400).
Required request part 'file' is not present
I don't have a stacktrace, that's all that's displayed in my window or my console. I've looked for other solutions and they all ended up being someone forgot to include name="file" in their html file. I have made sure it's included and am still getting the error.
Below is my upload form:
<div id="custom-search-input">
<label>Select a file to upload</label>
<form action="/upload" enctype="multipart/form-data" method = "post">
<div class="input-group col-md-12">
<input type="file" name="file" class="search-query form-control"/>
<span class="input-group-btn">
<button type="submit" class="btn btn-success">Upload </button>
</span>
</div>
</form>
</div>
This is my controller method for uploading:
#Value("${upload.path}")
private String path;
#RequestMapping("/upload")
public String upload(#RequestParam("file") MultipartFile file, Model model, HttpSession session) throws IOException {
if(!file.isEmpty()) {
//Get the user
User user = (User) session.getAttribute("user");
//Get the file name
String fileName = file.getOriginalFilename();
InputStream is = file.getInputStream();
//Store the uploaded file into the users directory in the system path
Files.copy(is, Paths.get(path + user.getNetworkId() + "\\" + fileName),StandardCopyOption.REPLACE_EXISTING);
return "redirect:/success.html";
} else {
return "redirect:/index.html";
}
}
Also would like to note I tried this for my upload method:
public String upload(#RequestParam(name="file",required=true) MultipartFile file, Model model, HttpSession session)
For reference, this is what I was referrencing.
As per some of the answers below, I tried creating a PostMapping method stand alone, as well as #RequestMapping(value="/upload", method = RequestMethod.POST) I am still getting the error.

After a while, I was able to solve this issue: In my application.properties file I added the following:
spring.servlet.multipart.max-file-size=128MB
spring.servlet.multipart.max-request-size=128MB
spring.http.multipart.enabled=true
upload.path=/export/home/

Your <form> in your view code is with method as POST
<form action="/upload" enctype="multipart/form-data" method = "post">
In controller change #RequestMapping("/upload") to below
#RequestMapping(value = "/upload", method = RequestMethod.POST)

you need something to handle loading the form a #GetMapping.
The #RequestMapping i think defaults to get. So when you are "getting" the page it tries to hit your method that is expecting a file. take a look at my example

I would recommend using #RequestPart. If you are uploading a file using from-data try to rewrite the code like below:
#PostMapping("/upload")
public ResponseEntity<CustomResponse> uploadFile(#RequestPart(value = "file",required = true) MultipartFile file,
#RequestPart(value = "metadata",required = true) Metadata metadata,
HttpServletResponse response)

I have had similar issue, in my case the reason was the name of the input tag of the form was not matching with #RequestParam("fileUpload") annotation parameters.
#PostMapping("/add")
public String addFile(#RequestParam("fileUpload") MultipartFile fileUpload, Model model, Authentication authentication) {
User loggeduser = userService.getUser(authentication.getName());
File newFile = new File();
String fileName = StringUtils.cleanPath(fileUpload.getOriginalFilename());
File fileaux = filesService.getFileByName(fileName);
int result = -1;
if (fileaux != null) {
model.addAttribute("result", false);
model.addAttribute("message", "File already exists");
return "result";
} else {
try {
newFile.setFilename(StringUtils.cleanPath(fileName));
newFile.setContentType(fileUpload.getContentType());
newFile.setFileSize(String.valueOf(fileUpload.getSize()));
newFile.setUserId(loggeduser.getUserid());
newFile.setFileData(fileUpload.getBytes());
result = filesService.addFile(newFile);
} catch (Exception e) {
e.printStackTrace();
}
}
if (result < 0) {
model.addAttribute("result", false);
} else {
model.addAttribute("result", true);
}
return "result";
}
it must match with the input form tag in the HTML file.
<form action="#" enctype="multipart/form-data" th:action="#{/file/add}" method="POST">
<div class="container">
<div class="row" style="margin: 1em;">
<div class="col-sm-2">
<label for="fileUpload">Upload a New File:</label>
</div>
<div class="col-sm-6">
<input type="file" class="form-control-file" id="fileUpload" name="fileUpload">
</div>
<div class="col-sm-4">
<button type="submit" class="btn btn-dark" id="uploadButton">Upload</button>
</div>
</div>
</div>

Related

How to stay on the same page after form submit thymleaf and Spring boot?

Hello guys i have a question regarding what is mentioned in the title. Is it possible to stay on the same page and submit . I found something with javascript but it is not working for me because i m using thymleaf and spring boot. Or i just don't know how to adapt it to my case.
thymeleaf code:
<form th:action="#{/tweets/tweet}" th:object="${tweet}" method="post">
<div class="row">
<div class="col">
<input type="text" th:field="*{content}" class="form-control" placeholder="What's happening? Tell us!">
</div>
<div class="col">
<input class="form-control" type="submit" value="Submit" />
</div>
</div>
</form>
the controller class:
#Controller
#RequestMapping("tweets")
#Slf4j
public class TweetController {
private TweetService tweetService;
public TweetController(TweetService tweetService) {
this.tweetService = tweetService;
}
#PostMapping("/tweet")
#ResponseStatus(CREATED)
public Tweet tweet(#Valid #ModelAttribute("tweet") Tweet tweet, Principal
principal, BindingResult result) {
if(result.hasErrors()){
//do somethign
}
if (!tweet.getContent().equals(null) && !tweet.getContent().equals("") && !tweet.getContent().isEmpty()) {
tweetService.createTweet(tweet.getContent(), principal);
}
}
#GetMapping("/")
public String goToIndex(Model model){
model.addAttribute("tweet",new Tweet());
return "overview";
}
And i have server.context-path=/api
I have one more additional question to this topic. When i wanted to redirect it to another page i was getting a blank page. Not an error not an exception just a blank page. Any help ? I m new to this.
Yes, this is possible using ajax. I would recommend doing it using jQuery though. So, if you would like to submit your form and stay in the same page, you could do the following.
HTML
<form id="tweet-form" th:action="#{/tweets/tweet}" th:object="${tweet}" method="post">
<div class="row">
<div class="col">
<input type="text" th:field="*{content}" class="form-control" placeholder="What's happening? Tell us!">
</div>
<div class="col">
<input id="submit-form" class="form-control" type="button" value="Submit" />
</div>
</div>
</form>
Changes:
Added an id to the form.
Added an id to your input.
Change submit input's type for button.
jQuery
$('#submit-form').on('click', function() {
var form = $('#tweet-form');
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: post,
success: function(result) {
// Do something with the response.
// Might want to check for errors here.
}, error: function(error) {
// Here you can handle exceptions thrown by the server or your controller.
}
})
}
Controller
#PostMapping("/tweet")
#ResponseStatus(CREATED)
public Tweet tweet(#Valid #ModelAttribute("tweet") Tweet tweet, Principal
principal, BindingResult result) {
if(result.hasErrors()){
// Throw an exception or send a null Tweet.
}
if (!tweet.getContent().equals(null) && !tweet.getContent().equals("") && !tweet.getContent().isEmpty()) {
tweetService.createTweet(tweet.getContent(), principal);
}
// You are returning a Tweet, so you must return something.
return tweet;
}
Your controller pretty much stay the same. Just remember to return something.
Your example doesn't show what the tweet() method returns. It should return a Tweet object but doesn't have any return value. What are you attempting to do with that return value? If you're not handling it with Javascript someway, then get rid of #ResponseStatus(CREATED) and return a either a Model or a String pointing to your html file, like so:
#PostMapping("/tweet")
public String tweet(#Valid #ModelAttribute("tweet") Tweet tweet, Principal
principal, BindingResult result) {
if(result.hasErrors()){
//do somethign
}
if (!tweet.getContent().equals(null) && !tweet.getContent().equals("") && !tweet.getContent().isEmpty()) {
tweetService.createTweet(tweet.getContent(), principal);
}
return "redirect:/name-of-html-file";
}
reference
If you want thymeleaf to handle the tweet and the HttpStatus you could instead return something along the lines of
ModelAndView model = new ModelAndView("your-view");
model.addAttribute(tweet);
model.setStatus(HttpStatus.CREATED);
return model;

Solution for issue in Redirect or RedirectModel in SpringMVC

I have currently built a controller for my index page which is also a login page.
With the controller, I'm mapping the jsp if the login credentials of the user matches and if it doesn't I want to redirect to the index page with message "Sorry Username, Password error."
Here's the code:
Controller
if(uname.equals(inf.getUsername())&&pwd.equals(inf.getPassword())&&dept.equals(inf.getDept()))
{
req.getSession().setAttribute("uname",inf.getName());
return new ModelAndView("employeeLoginResult", "message", message1);
}
else if(uname.equals(inf2.getUsername())&&pwd.equals(inf2.getPassword())&&dept.equals(inf2.getDept()))
{
req.getSession().setAttribute("uname",inf2.getName());
return new ModelAndView("adminLoginResult", "message", message2);
}
else
{
return new ModelAndView("redirect:/index.jsp","message","Sorry");
}
The index page
<b><span class="heading">LOGIN USER</span></b>
<div class="container">
<form action="login.html" method="Post">
<div class="form_style">
<input type="text" name="username" placeholder="Enter Username"/>
<input type="password" name="pwd" placeholder="Enter password"/>
<select name="dept">
<option>IT</option>
<option>Admin</option>
<option>HR</option>
<option>Marketing</option>
</select>
<input type="Submit" value="submit">
<span class='disp'>${message}</span>
</div>
</form>
</div>
The redirect works but the message get appended in the Url like this:
I just want to print "Sorry username password error" on the index file with ${message}
My question:
Is it possible to use ModelAndView with RedirectView or if it isn't are there any other solution to send redirect to my index page with using ModelAndView?
Any suggestions or opinions are appreciated.
Thanks for the same.
"The redirect works but the message get appended in the Url " this is the expected behaviour of normal redirection attributes.
You can use flash attributes to redirect by not revealing the URL in the browser.
For example refer below code :
#RequestMapping(value = "/accounts", method = RequestMethod.POST)
public String handle(Account account, BindingResult result, RedirectAttributes redirectAttrs) {
if (result.hasErrors()) {
return "accounts/new";
}
// Save account ...
redirectAttrs.addAttribute("id", account.getId()).addFlashAttribute("message", "Account created!");
return "redirect:/accounts/{id}";
}
Refer this : https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/support/RedirectAttributes.html
Can you add a class like MyConfig
#EnableWebMvc
#Configuration
public class MyConfig {
#Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
#PostConstruct
public void init() {
requestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(true);
}
}

Upload an image and refresh the img tag

Im am using Springboot and embedded server (Jetty) in my application.
I want to upload an image and reload my html page to show the new image in an img tag.
Th file is uploaded well and saved in a folder of my app. But when I reload my page, I can't see my new image.
It seems that my embedded server can't see my new files. When I rebuilt my project I can see the new file.
How can I do to refresh automatically my img tag without rebuilting my project
Here is my html page
<img th:src="#{/images/scan/}+${signatureScannedImg}" style="margin-bottom: 30px"/>
<form th:action="#{/upload-signature-scan}" th:method="post" enctype="multipart/form-data">
<table>
<tr><td><input type="file" name="file" /></td></tr>
<tr><td><input type="hidden" id="scannedFile" name="scannedFile" value="signature" /></td></tr>
<tr><td><input type="hidden" id="idClient" name="idClient" th:value="${clientView.id}" /></td></tr>
<tr><td><input type="submit" value="Enregistrer" /></td></tr>
</table>
</form>
And my controller method is :
#RequestMapping(value = "/upload-signature-scan", method = RequestMethod.POST)
public String handleFileUpload(
#RequestParam("file") MultipartFile file,
#RequestParam("idClient") Long idClient,
#RequestParam("scannedFile") String scannedFile,
RedirectAttributes redirectAttributes) {
Path rootLocation= Paths.get("src/main/resources/static/images/scan");
try {
Files.copy(file.getInputStream(), rootLocation.resolve("image.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
redirectAttributes.addAttribute("id", idClient);
redirectAttributes.addFlashAttribute("id", idClient);
redirectAttributes.addFlashAttribute("signatureScannedImg", "image.jpg");
return "redirect:/client/{id}/details";
}
I found the solution here : https://spring.io/guides/gs/uploading-files/
Thank you

Spring MVC mapped method not being called using POST

I am trying to upload a file using Spring MVC.
Here is the form in the .jsp page
<form:form method="post" commandName="file" enctype="multipart/form-data">
Upload your file please:
<input type="file" name="file" />
<input type="submit" value="upload" />
<form:errors path="file" cssStyle="color: #ff0000;" />
</form:form>
In my controller I have the GET and POST methods:
#RequestMapping(method = RequestMethod.GET)
public String getForm(Model model) {
File fileModel = new File();
model.addAttribute("file", fileModel);
return "file";
}
#RequestMapping(method = RequestMethod.POST)
public String fileUploaded(Model model, #Validated File file, BindingResult result) {
String returnVal = "successFile";
logger.info("I am here!!!");
if (result.hasErrors()) {
returnVal = "file";
}else{
MultipartFile multipartFile = file.getFile();
}
return returnVal;
}
The validation is just to check if the file size is zero:
public void validate(Object target, Errors errors) {
File imageFile = (File)target;
logger.info("entered validator");
if(imageFile.getFile().getSize()==0){
errors.rejectValue("file", "valid.file");
}
}
The method GET works fine and returns the file view, however the POST method in the controller does not get called. Nothing happens when the upload button is clicked.
I hope this will help you:
controller code
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String uploadInputFiles(#RequestParam("file1") MultipartFile file,
#RequestParam("fileName") String fileName,
#RequestParam("fileType") String fileType){
System.out.println("Upload File Controller has been called");
}
Form submission:
<form method="POST" action="uploadFile" enctype="multipart/form-data">
File to upload: <input type="file" name="file"><br />
Name: <input type="text" name="name"><br /> <br />
<input type="submit" value="Upload"> Press here to upload the file!
</form>
I think your configuration should be like below in mvc-servlet.xml file.
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="500000" />
</bean>
and change your post api like below.
#RequestMapping(method = RequestMethod.POST,value = "/uploadFile")
public String fileUploaded(Model model, #RequestParam("file") MultipartFile file, BindingResult result) {
String result = "not uploaded";
if(!file.isEmpty()){
MultipartFile multipartFile = file.getFile();
//code for storing the file in server(in db or system)
}
else{
result = "can not be empty;"
}
return result;
}

Multipart File submit never hit the server method

I have an ajax call:
what happens is that I click on an Image that clicks on "input file" that I don't want it to be shown. when the input val() is changed method uploadListener() is invoked which is basically an ajax method that get the file to the server "upload it to server"
code goes like this:
html:
<img id="${assayAssessRequest.id}" src="[#spring.url '/images/buttons/upload.jpg'/]" onclick="uploadFile(this);" title="Upload File" />
<form id="uploadForm" action="[#spring.url '/assay/designability/uploadFile.htm'/]" method="POST" enctype="multipart/form-data">
<div style="display: none;">
[#spring.formInput path="multiPartBean.file" fieldType="file" attributes="title='path' class='upload' accept='.txt,.csv,.zip'" /]
[#spring.formHiddenInput path="multiPartBean.fileName" attributes=" onchange='uploadListener();'class='uploadFileName'" /]
[#spring.bind "multiPartBean"/]
</div>
<input type="submit" id="uploadButton" value="upload" />
</form>
javaScript:
function uploadFile(){
document.getElementById('inputFile').click();
}
function uploadListener(){
$('#uploadForm').attr("action","[#spring.url '/assay/designability/uploadFile.htm'/]");
alert($('#uploadForm').attr('action'));
this.document.getElementById("uploadForm").submit = true;
alert("After Submit");
return false;
}
server controller:
#Controller
#PreAuthorize("isAuthenticated()")
#RequestMapping("/assay/designability")
#SessionAttributes({"assayAssessmentsInitializersBean","assayAssessmentsRequestsDetailsBean"})
public class AssayDesignabilityController extends AssayBaseController {
#RequestMapping(value = "/uploadFile",method= RequestMethod.GET)
public String uploadFile(#RequestParam(value = "file")Object file){
MultipartFile multipartFile=(MultipartFile)file;
logger.info(multipartFile.getName());
return multipartFile.getName();
}
}
now when I do all that, the response give me nonsense and when I try to debug I never get to the controller method. any help??
EDIT:
now I try to submit it I've updated code and I have the same behavior no response.
I've solved my problem by avoiding ajax call and re implement my code thanks to #Ian.
here is the code:
Html plus Freemarker
<form id="uploadForm" action="#" method="POST" enctype="multipart/form-data">
<div class="instruction popup_inst">
<span class="popup_logo">[#spring.message "pandaLogo"/]</span>
<div class="float_right">
<input type="button" id="cancelBtn" class="btn" onclick="refreshParentTable();closePopup();" value="[#spring.message "cancelButton"/]" />
<input class="btn" type="submit" id="submit" onclick="validateFileInput();" value="[#spring.message "uploadButton"/]" />
</div>
</div>
<span class="popup_title">[#spring.message "uploadFile"/]</span>
<div class="popup_container">
[#spring.bind "assayAssessmentsRequestBean"/]
[#spring.formInput path="assayAssessmentsRequestBean.designabilityFile.file" fieldType="file" attributes="title='path' class='upload' accept='.txt,.csv,.zip'" /]
[#spring.formHiddenInput path="assayAssessmentsRequestBean.designabilityFile.fileName" attributes="class='uploadFileName'" /]
[#spring.formHiddenInput path="assayAssessmentsRequestBean.dateOfAssessment" attributes="" /]
[#spring.formHiddenInput path="assayAssessmentsRequestBean.id" attributes="" /]
</div>
<input id="uploadfile" type="hidden" value="${uploadfile}"/>
</form>
controller:
#RequestMapping(value = "/uploadFile",method= RequestMethod.POST)
public ModelAndView uploadFile(#ModelAttribute(value = "assayAssessmentsRequestBean")AssayAssessmentsRequestBean assayAssessmentsRequestBean,HttpSession session) throws PanDaApplicationException {
//mycode
}
from this experience I would advice evreyone to avoid sending files via ajax calls for me
I used a popup window to create form and submit upload operation.
Thanks for everyone tried to help
If i see correctly, the submit action points to "uploadfile.HTM"
$('#uploadForm').attr("action","[#spring.url '/assay/designability/uploadFile.htm'/]");
but the method in your controller is mapped only to uploadFile (without .htm)
#RequestMapping(value = "/uploadFile",method= RequestMethod.GET)
Maybe you have another configuration on your web.xml / servlet-spring.xml that makes this possible, but otherwise, this could be the problem.
Hope this helps
Regards

Categories