Проблема с Spring FileUpload - PullRequest
       4

Проблема с Spring FileUpload

9 голосов
/ 20 сентября 2010

У меня есть следующий блок кода, который обрабатывает загрузку файла фотографии, которую я использую в своем веб-приложении Spring MVC. Я использую Spring MVC CommonsMultipartFileResolver для обработки загрузки файлов.

if(model.getPhoto() != null){
    if(!model.getPhoto().isEmpty()){
        MultipartFile file = model.getPhoto();
        String fileName = file.getOriginalFilename();
        String filePath = baseDirectory + fileName;
        FileOutputStream fos = new FileOutputStream(filePath);
         try 
         {
            fos.write(file.getBytes());
            agentProfile.setPhotoUri(fileName);
         } 
         catch (IllegalStateException e) 
         {
            System.out.println(e);

         }
         finally   
         {
             fos.close();
         }
    }
}

В моем файле app-servlet.xml у меня есть следующий код для настройки bean-компонента распознавателя MultipartFile.

 <bean id="multipartResolver"   class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
 </bean>

У меня возникают некоторые случайные проблемы при загрузке фотографий.

1) Если я загружу фотографию меньшего размера, около 3 КБ или около того, она будет успешно загружена.

2) Если я пойду, чтобы загрузить немного большую фотографию, он создаст файл в каталоге, но с размером 0 байт и выдаст следующее сообщение об ошибке.

 java.lang.IllegalStateException: File has been moved - cannot be read again
org.springframework.web.multipart.commons.CommonsMultipartFile.getBytes(CommonsMultipartFile.java:112)
com.mmz.admin.mvc.controller.AddAgentController.processFinish(AddAgentController.java:145)
org.springframework.web.servlet.mvc.AbstractWizardFormController.validatePagesAndFinish(AbstractWizardFormController.java:642)
org.springframework.web.servlet.mvc.AbstractWizardFormController.processFormSubmission(AbstractWizardFormController.java:492)
org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:265)
org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

Я испробовал несколько различных вариантов настройки многочастного преобразователя, таких как переключение его для обработки CommonsMultipartFile объекта в отличие от простого MultipartFile объекта, но ничего не изменилось.

Я также попытался вручную настроить максимальный размер загрузки в bean-компоненте CommonsMultipartFileResolver со следующим свойством.

 <property name="maxUploadSize" value="1024000000"/>  

ничего не изменилось. Я не уверен, что CommonsMultipartResolver по умолчанию соответствует размеру файла, который может быть загружен, но это не мой вопрос.

Мне сказали, что проблема, с которой я сталкиваюсь, связана с проблемой в парсере / обработчике Multipart, который использует spring. У меня был недавний пост об этой же проблеме, и, поскольку была найдена новая информация, я хотел опубликовать новую информацию. Старый пост можно найти по адресу CommonsMultipartFileResolver Проблема

Мне кажется, что я проверил почти все ресурсы в Интернете, чтобы найти дополнительную документацию, но не могу выяснить проблему.

Пожалуйста, помогите мне выяснить, что происходит с этим, и, если есть лучшее, более простое решение, возможно, для изучения этих опций, но я бы предпочел остаться с моим текущим методом, если я могу найти решение.

EDIT Примечание. Я экспериментировал с фотографиями разных размеров для загрузки, и я считаю, что ограничение, которое он позволяет загружать, составляет около 10 КБ. Все, что больше 10Kb, вызывает его поломку и выдает ошибку выше.

Ответы [ 3 ]

12 голосов
/ 20 сентября 2010

После долгих исследований я решил свою проблему. Оказывается, что для максимального количества байтов, которое вы можете загрузить с помощью CommonsMultipartFileResolver , не установлено ограничение по умолчанию. Конечно, вы можете указать в своем бине все, что хотите для этой суммы, установив следующее свойство.

<property name="maxUploadSize" value="99999999999"/>

Существует также свойство maxInMemorySize , которое позволяет указать максимально допустимый размер до записи файлов на диск. Хотя это работает так же, как и максимальный размер загрузки, если вы не укажете сумму, по умолчанию используется значение 1024 байта. Это объясняет его поломку, если я попытался загрузить большой файл.

Чтобы разрешить загрузку файлов размером более 1024 байт, вам нужно увеличить значение maxInMemorySize до следующего:

Вот что позаботилось о моей проблеме. Я узнал, что это свойство по умолчанию равно 1024, когда я просматривал документацию для CommonsFileUpload Documentation.

Вы можете просмотреть эту документацию по Документация CommonsFileUpload

Надеюсь, это кому-нибудь поможет, поскольку не очень хорошая документация по использованию CommonsMultipartFile.

3 голосов
/ 06 февраля 2014

Я заметил, что эта ошибка возникает только тогда, когда размер файла превышает 1024 байта И вы пытаетесь прочитать файл дважды .Как упоминает CitadelCSAlum, установка maxInMemorySize = maxUploadSize решит эту проблему, но следует учитывать использование памяти.Если проблема связана с памятью, другой вариант - записать данные многочастного файла во временный файл при первом чтении и использовать этот файл для последующих чтений.Если вы не читаете дважды, вам не нужно увеличивать maxInMemorySize.

2 голосов
/ 21 июня 2014

Исключение, на которое вы ссылаетесь в своем вопросе, гласит: «Файл перемещен - его невозможно прочитать снова».Это потому, что мы пытаемся прочитать входной поток более одного раза из многокомпонентного файла.

Я также однажды столкнулся с этой проблемой, и в моем случае сначала я проверил содержимое файла, а после этого япопытался сохранить его с помощью метода «TransferTo» в Spring MultiPart.Это исключение возникает, когда я пытаюсь использовать метод "TransferTo".Здесь я дважды призываю к inputtream.

Я не сталкиваюсь с этой проблемой, когда размер файла слишком мал.В методе TransferTo происходит внутренний вызов метода isAvailable.Пожалуйста, следуйте приведенному ниже фрагменту кода:

    protected boolean More ...isAvailable() {
            // If in memory, it's available.
        if (this.fileItem.isInMemory()) {
            return true;
        }
        // Check actual existence of temporary file.
        if (this.fileItem instanceof DiskFileItem) {
            return ((DiskFileItem) this.fileItem).getStoreLocation().exists();
        }
        // Check whether current file size is different than original one.
        return (this.fileItem.getSize() == this.size);
    }

ссылка: http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-web/3.2.1.RELEASE/org/springframework/web/multipart/commons/CommonsMultipartFile.java#CommonsMultipartFile.isAvailable%28%29

Замечания:

  1. Если он слишком мал, сохраните его веснойв памяти, и когда мы просим файл, он извлекается из памяти.Мы можем запросить его несколько раз, потому что файл находится в памяти.

  2. Если он достаточно большой, Spring сохранит его как временный файл, местоположение которого мы не знаем, но после того, какчитать входные данные, как только этот файл может быть удален изнутри Spring.Затем, когда мы просим во второй раз, что ошибка говорит «не может быть прочитано снова».

Поэтому мое решение - сначала я должен сохранить его в серверной транзакции, используя метод «TransferTo», и извлечьэтот локальный файл для проверки или любой другой второй раз.

Я думаю, что не стоит увеличивать "maxUploadSize" в компоненте "multipartResolver", так как он потребляет больше памяти, если файл слишком велик.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...