phcaze
phcaze

Reputation: 1777

Spring MVC Multipart file upload random FileNotFoundException

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

Answers (2)

tahir
tahir

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

kholofelo Maloma
kholofelo Maloma

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

Related Questions