2010-09-19 7 views
8

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

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

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

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

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

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

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

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

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

+0

см. Http://stackoverflow.com/questions/11792107/multipartresolver-is-not-working – lrkwz

ответ

11

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

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

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

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

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

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

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

+1

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

+0

Буду считать, я собираюсь подробнее разобраться в этом вопросе. Удивительно, что они будут по умолчанию от 1024 до 1024, если ничего не указано, но не другое. – TheJediCowboy

+0

Согласно ссылке, которую вы ссылаетесь, значение по умолчанию составляет 10240 байт (объясняя ваш предыдущий эмпирический результат). –

3

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

2

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

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

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

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

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

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

+1

Это не отвечает на вопрос. Если у вас есть другой вопрос, вы можете задать его, нажав [Ask Question] (http://stackoverflow.com/questions/ask). Вы также можете [добавить щедрость] (http://stackoverflow.com/help/privileges/set-bounties), чтобы привлечь больше внимания к этому вопросу, как только у вас будет достаточно [репутации] (http://stackoverflow.com/help/ Что-репутация). – apaul

+0

Я не согласен с этим. Это исключение возникает при вызове метода getBytes в классе «CommonsMultipartFile». В моем случае я использую метод «transferTo», и в обоих случаях он будет вызывать метод «isAvailable». Если мы уже используем входной поток этого многостраничного файла, это исключение произойдет. Поэтому мое решение сначала нужно сохранить этот файл в местоположении сервера и получить этот файл для любых проверок. Поскольку, если этот предел превышен, Spring сохранит этот файл на диске, а не в памяти. Когда мы читаем, как только он удалит этот временный файл на диске. Но если он слишком мал, он будет находиться в памяти. – Arosha

+0

Извините, что, учитывая формулировку/форматирование вашего ответа, это выглядело как комментарий «У меня такая же проблема». Я отступил назад. – apaul

Смежные вопросы