Reputation: 1777
I built a web application using spring MVC, everything is working fine except the file upload in which I got random FileNotFoundExceptions. I found some solutions online like using a different tmp folder but I keep getting random error.
My code is:
@RequestMapping(value="/upload", method=RequestMethod.POST)
public @ResponseBody String handleFileUpload(@RequestParam("file") final MultipartFile multipartFile,
@RequestHeader("email") final String email, @RequestHeader("password") String password){
if (authenticateUser(email, password)) {
if (!multipartFile.isEmpty()) {
System.out.println("Start processing");
Thread thread = new Thread(){
public void run(){
ProcessCSV obj = new ProcessCSV();
try {
File file = multipartToFile(multipartFile);
if(file !=null) {
obj.extractEvents(file, email, cluster, session);
}
else {
System.out.println("null File");
}
} catch (IOException e) {
System.out.println("File conversion error");
e.printStackTrace();
}
}
};
thread.start();
return "true";
} else {
return "false";
}
}
else {
return "false";
}
}
and:
public File multipartToFile(MultipartFile multipartFile) throws IOException {
File uploadFile = null;
if(multipartFile != null && multipartFile.getSize() > 0) {
uploadFile = new File("/tmp/" + multipartFile.getOriginalFilename());
FileOutputStream fos = null;
try {
uploadFile.createNewFile();
fos = new FileOutputStream(uploadFile);
IOUtils.copy(multipartFile.getInputStream(), fos);
} catch (FileNotFoundException e) {
System.out.println("File conversion error");
e.printStackTrace();
} catch (IOException e) {
System.out.println("File conversion error");
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
System.out.println("File conversion error");
e.printStackTrace();
}
}
}
}
else {
System.out.println("null MultipartFile");
}
return uploadFile;
}
and the configuration file:
multipart.maxFileSize: 100MB
multipart.maxRequestSize: 100MB
multipart.location = ${user.home}
server.port = 8090
I used different versions of the multipartToFile function, one was using multipartfile.transferTo()
but I was getting the same random error. Any advice?
Thank you
EDIT stack trace:
java.io.IOException: java.io.FileNotFoundException: /Users/aaa/upload_07720775_4b37_4b86_b370_40280388f3a4_00000003.tmp (No such file or directory)
at org.apache.catalina.core.ApplicationPart.write(ApplicationPart.java:121)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.transferTo(StandardMultipartHttpServletRequest.java:260)
at main.RESTController.multipartToFile(RESTController.java:358)
at main.RESTController$1.run(RESTController.java:241)
Caused by: java.io.FileNotFoundException: /Users/aaa/upload_07720775_4b37_4b86_b370_40280388f3a4_00000003.tmp (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.write(DiskFileItem.java:392)
at org.apache.catalina.core.ApplicationPart.write(ApplicationPart.java:119)
... 3 more
Upvotes: 5
Views: 7570
Reputation: 31
I had the same problem, it looks like MultipartFile is using different current dir internally, so all not absolute paths are not working. I had to convert my path to an absolute path and then it worked. It is working inside @RestController and in other beans too.
Path path = Paths.get(filename).toAbsolutePath();
fileToImport.transferTo(path.toFile());
fileToImport is MultipartFile.
Upvotes: 3
Reputation: 1003
I had just had a night of terror with this error. I found out that MultiPartFile
is only recognisable to and by the @Controller
class. So if you pass it to another bean which is not a controller, Spring will not be able to help you. It somewhat makes sense that the @Controller
is tightly bound to the front screen (communication from the browser to the system - Controllers are the entry point from the browser). So any conversation must happen there in the Controller.
In my case, I did something like the following:
@Controller
public class FileUploadingController{
@PostMapping("/uploadHistoricData")
public String saveUploadedDataFromBrowser(@RequestParam("file") MultipartFile file) {
try {
String pathToFile = "/home/username/destination/"
new File(pathToFile).mkdir();
File newFile = new File(pathToFile + "/uploadedFile.csv");
file.transferTo(newFile); //transfer the uploaded file data to a java.io.File which can be passed between layers
dataService.processUploadedFile( newFile);
} catch (IOException e) {
//handle your exception here please
}
return "redirect:/index?successfulDataUpload";
}
}`
Upvotes: 6