上传文件停止,并在套接字Exception上读取意外的EOF

时间:2016-01-06 13:35:28

标签: java spring spring-mvc tomcat

有时当我尝试在远程vps上传文件时,我会收到此异常(上传过程停止在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

并且在Google Chrome中,如果服务器关闭,连接就会丢失,我得到ERR_CONNECTION_ABORTED

我在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() ); ;
        }

}

我的控制员:

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

我的豆子

public class UploadForm {

    ...
    public MultipartFile scan;

那怎么能解决这个问题呢?

5 个答案:

答案 0 :(得分:5)

你试过流吗?

Jsp代码:

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

控制器:

 @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

}

所有这些都适用于我的春季4.0和春季安全。

其次,您应该检查http连接是否超时。 Chrome不支持该配置。所以你可以使用firefox并点击这里http://morgb.blogspot.com.es/2014/05/firefox-29-and-http-response-timeout.html

答案 1 :(得分:2)

出现此问题是因为您关闭流直到流写入整个数据。

错误的方式:

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

正确的方式:

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

您应该在写完整个数据后关闭您的信息流。

答案 2 :(得分:1)

不确定upfile上的getBytes()方法。更合适的方法是使用InputStream来管理任何大小的文件,并在必要时进行缓冲。类似的东西:

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() ); ;
    }

}

答案 3 :(得分:1)

我有类似的问题和问题,当你上传文件时,你正在使用Multipart Form POST Request。你可以阅读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--

基本上我遇到的问题是来自请求的多部分有元信息部分,文本部分和实际文件编码我相信base64。每个部分都按边界分割。如果您没有设置此边界(例如上面的示例,它被称为&#34; frontier&#34;)正确的服务器开始读取文件但是在它到达EOF之前不知道它的结束位置并返回有关意外EOF的错误,因为它没有找到所需的边界。

您的代码问题在于您正在将文件写入ByteOutputStream,这适用于将文件从服务器返回给用户而不是其他方式。服务器期望这个Multipart请求具有一些标准的预定义格式。使用Apache Commons HttpClient库为您执行所有此请求格式化和边界设置。如果你使用Maven然后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);

免责声明:代码不是我的代码Apache website for multipart request

答案 4 :(得分:0)

当我没有正确设置文件放置路径时,我遇到了同样的错误。

解决方法是像这样更改它:

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

并在控制器中使用throws异常:

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

并确保不要发送任何已经存在的同名文件。