Остановка загрузки файла с непредвиденным EOF, прочитанным в сокете Исключение

Когда-нибудь, когда я пытаюсь загрузить файл на своем удаленном 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 {

my bean

public class UploadForm {

    ...
    public MultipartFile scan;

Итак, как решить эту проблему?

Ответы

Ответ 1

Вы пробовали поток?

Код 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

}

Все, что сработало для меня с spring 4.0 и spring безопасностью.

Во-вторых, вы должны проверить, является ли HTTP-соединение таймаутом. Chrome не поддерживает эту конфигурацию. Таким образом, вы можете использовать firefox и следовать здесь http://morgb.blogspot.com.es/2014/05/firefox-29-and-http-response-timeout.html.

Ответ 2

Не уверен в методе getBytes() в upfile. Более подходящим подходом было бы использовать 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

У меня были похожие проблемы, и проблема заключается в том, что вы загружаете файл, в котором используется запрос POST для многостраничной формы. Вы можете прочитать о 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--

В основном проблема была в том, что у multipart from request есть метаинформационная часть, текстовая часть и фактический файл, закодированный, я верю в base64. Каждая из этих частей разделяется границей. Если вы не настроили эту границу (в приведенном выше примере она называется "граница" ), сервер начинает читать файл, но не знает, где он заканчивается до тех пор, пока он не достигнет EOF и не вернет ошибку о неожиданном EOF, потому что он не нашел нужным границы.

Проблема с вашим кодом заключается в том, что вы записываете файл в ByteOutputStream, который подходит при возврате файла с сервера пользователю не по-другому. Сервер ожидает этот запрос Multipart с некоторым стандартным предопределенным форматированием. Используйте библиотеку Apache Commons HttpClient, которая выполняет все эти настройки запроса и настройки границ для вас. Если вы используете Maven, то эта ссылка.

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 для многопрофильного запроса

Ответ 4

Эта проблема возникает из-за того, что вы закрываете поток, пока поток не будет записывать целые данные.

Неправильно:

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

Правильный путь:

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

Вы должны закрыть свой поток после того, как будут записаны все данные.