20

Sometime when I try to upload a file on my remote vps i get this exception (the upload proccess stop in 60%)

06-Jan-2016 11:59:36.801 SEVERE [http-nio-54000-exec-9] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [mvc-dispatcher] in context with path [] threw exception [Request processing failed;
nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request;
nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Unexpected EOF read on the socket]
with root cause
 java.io.EOFException: Unexpected EOF read on the socket

and in Google Chrome the connextion is lost like the server is down, i get ERR_CONNECTION_ABORTED

i upload file like this in spring mvc

public void save_file(MultipartFile upfile , String path){

        try {

            File fichier = new File( path ) ;
            byte[] bytes = upfile.getBytes();
            BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream( fichier ));
            stream.write(bytes);
            stream.close();
            System.out.println( "You successfully uploaded " + upfile.getOriginalFilename() + "!" );

        } catch (Exception e) {
            System.out.println( "You failed to upload " + upfile.getOriginalFilename() + " => " + e.getMessage() ); ;
        }

}

my controller :

@RequestMapping(value = "/administration/upload", method = RequestMethod.POST)
public String Upload_AO_journal(
        @ModelAttribute  UploadForm uploadForm,
                Model map , HttpServletRequest request, HttpSession session ) throws ParseException, UnsupportedEncodingException {

my bean

public class UploadForm {

    ...
    public MultipartFile scan;

So how can solve this problem ?

user207421
  • 305,947
  • 44
  • 307
  • 483
Hayi
  • 6,972
  • 26
  • 80
  • 139
  • Does it fail for all file sizes, or do small files succeed? Can you share the spring specific code that maps the request to this method? – tdimmig Jan 11 '16 at 21:00
  • @tdimmig sometimes it fails and sometimes for the same size it's okey !! i update my question. – Hayi Jan 11 '16 at 21:04
  • 1
    See if this answer can help you out: http://stackoverflow.com/a/18543887/4056187 – robert Jan 11 '16 at 21:36

5 Answers5

6

Have you tried stream?

Jsp code:

<form method="POST" onsubmit="" ACTION="url?${_csrf.parameterName}=${_csrf.token}" ENCTYPE="multipart/form-data">

Controller:

 @RequestMapping(
        value = "url", method = RequestMethod.POST
)
public void uploadFile(
        @RequestParam("file") MultipartFile file
) throws IOException {

 InputStream input = upfile.getInputStream();
 Path path = Paths.get(path);//check path
 OutputStream output = Files.newOutputStream(path);
 IOUtils.copy(in, out); //org.apache.commons.io.IOUtils or you can create IOUtils.copy

}

All that worked for me with spring 4.0 and spring security.

Secondly, you should check if the http connection is timeout. Chrome does not support that configuration. So you can use firefox and follow here http://morgb.blogspot.com.es/2014/05/firefox-29-and-http-response-timeout.html.

ahll
  • 2,329
  • 1
  • 19
  • 22
  • The apache api for file is more secure than the default java api for files ? – Hayi Jan 18 '16 at 12:28
  • I used it, just because it is clean and tested. I donot think it is more secure. – ahll Jan 18 '16 at 17:37
  • @Youssef I am facing a similar issue, but in my case I am closing the streams in a finally block. Is it not required to close the input and output streams here? – Shashank Shekher Jan 13 '22 at 04:08
2

Not sure about the getBytes() method on the upfile. A more suitable approach would be to use the InputStream which will manage any size file and will buffer when necessary. Something like:

public void save_file(MultipartFile upfile , String path){

    try {
        File fichier = new File( path ) ;
        BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream( fichier ));
        InputStream is = upfile.getInputStream();
        byte [] bytes = new byte[1024];
        int sizeRead;
        while ((sizeRead = is.read(bytes,0, 1024)) > 0) {
            stream.write(bytes, 0, sizeRead);
        }
        stream.flush();
        stream.close();
        System.out.println( "You successfully uploaded " + upfile.getOriginalFilename() + "!" );

    } catch (Exception e) {
        System.out.println( "You failed to upload " + upfile.getOriginalFilename() + " => " + e.getMessage() ); ;
    }

}
Mike Murphy
  • 1,006
  • 8
  • 16
2

This issue appears because you close stream until stream write whole data.

Wrong way:

stream.write(bytes);
stream.close();

Right way:

try (BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fichier))) 
{
    stream.write(data);
}

You should close your stream after whole data is written.

N00b Pr0grammer
  • 4,503
  • 5
  • 32
  • 46
eg04lt3r
  • 2,467
  • 14
  • 19
1

I had similar issues and problem is when you are uploading file you are using Multipart Form POST Request. You can read about MIME .

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=frontier

This is a message with multiple parts in MIME format.
--frontier
Content-Type: text/plain

This is the body of the message.
--frontier
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64

PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg
Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==
--frontier--

Basically issue I had was that multipart from request has meta information part, text part and actual file encoded I believe in base64. Each of this parts are split by boundary. If you don't set up this boundary (in example above it's called "frontier") correctly server starts reading the file but doesn't know where it ends until it reaches EOF and returns error about unexpected EOF because it didn't found required boundaries.

Problem with your code is that you are writing file into ByteOutputStream which is suitable when returning file from server to the user not other way around. Server is expecting this Multipart request with some standard predefined formatting. Use Apache Commons HttpClient library that does all this request formating and boundary setting for you. If you use Maven then this link.

File f = new File("/path/fileToUpload.txt");
PostMethod filePost = new PostMethod("http://host/some_path");
Part[] parts = {
  new StringPart("param_name", "value"),
  new FilePart(f.getName(), f)
};
filePost.setRequestEntity(
  new MultipartRequestEntity(parts, filePost.getParams())
  );
HttpClient client = new HttpClient();
int status = client.executeMethod(filePost);

Disclaimer: code is not mine it's example from Apache website for multipart request

MichaelDD
  • 766
  • 6
  • 14
  • Well from his question I understood that he's uploading from Spring Client because he said "i upload file like this in spring mvc" that's why I assumed he's uploading from client – MichaelDD Jan 15 '16 at 12:30
  • I guess he meant something like 'into'. He is uploading using google chrome on the client and has Spring MVC on the server side. – Michal Jan 15 '16 at 12:47
  • @MichaelDD yes i use browser – Hayi Jan 18 '16 at 11:32
  • 1
    Oh ok my apologies I didn't correctly understand the question. I was having same issue when uploading from client so I assume that's your case as well – MichaelDD Jan 18 '16 at 12:16
  • No problem bro .. i can face your problem in the future – Hayi Jan 18 '16 at 12:27
0

I got the same error when I didn't properly set the path where the file is going to be placed.

The fix was to change it like this:

factoryMaster.setCertificateFile("E:\\Project Workspace\\Live Projects\\fileStore\\Factory Master\\"+factoryMasterBean.getFile().getOriginalFilename());

and use throws exception in controller:

public @ResponseBody ResponseEntity<FactoryMaster> saveFactoryMaster(@ModelAttribute("factoryMasterBean") FactoryMasterBean factoryMasterBean,FactoryMaster factoryMaster) throws IllegalStateException, IOException {...............}  

and make sure do not send any file with the same name which already exists.