2013-08-29 4 views
2

Я хочу загрузить изображения, которые являются 2MB - 10MB, на мой сервер и сохранять их непосредственно на жесткий диск. Цель состоит в том, чтобы сохранить как можно больше памяти кучи моего JVM, потому что, если пользователь одновременно загружает мою систему, ее не следует сбрасывать.Эффективная загрузка файлов/изображений в Java?

Вот как я это делаю в данный момент. Когда запрос с загрузкой прийти в мой контроллер я:

CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image') 
InputStream inputStream = file.inputStream 
byte [] byteFile = inputStream.getBytes() 

try{ 
    def fullPath = // some image path and file name 
    def newFile = new FileOutputStream(fullPath) 
    newFile.write(byteFile) 
    newFile.close() 
} 
catch(IOException e){ } 

Here Я читал, что есть ImageIO и java.awt.Toolkit, где Инструментарий должен быть быстрым, чтобы сохранить файл.

Как я могу улучшить свою загрузку для использования как можно меньше кучи и загрузить как можно быстрее?

Альтернатива 1:

Альтернативой может быть:

CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image') 
def fullPath = // some image path and file name 
file.transferTo(new File(fullPath)) 

Какой из них лучше?

ответ

2

Ваш текущий код получает входной поток с содержимым файла, но затем загружает все содержимое этого потока в byte[] перед тем, как записать его в файл на диске. Ваши «альтернативные 1» потоки непосредственно из входного потока в файл на диске будут намного эффективнее с точки зрения памяти и, по крайней мере, так же быстро, как и ваш текущий метод буферизации (возможно, быстрее, поскольку на пути меньше мусора).

+0

Является ли моя альтернатива 1 такой же: http://commons.apache.org/proper/commons-fileupload/streaming.html? Это так быстро? –

+0

@ stephan1001 с использованием 'transferTo' всегда должен быть самым быстрым способом делать то, что вы хотите. Commons-fileupload буферизирует небольшие загрузки в память и передает большие файлы во временные файлы на диске. Вызов 'transferTo' будет выгружать буфер, если файл уже буферизирован в память или переименует временный файл, если он может, или сделать поточную копию из временного файла в пункт назначения, если он не может. Предоставление фреймворкам наиболее эффективного подхода для каждого файла с использованием его «знаний инсайдеров» никогда не будет медленнее, чем выбрать один подход самостоятельно и использовать его безоговорочно. –

+0

Является ли кодирование того, что мне нужно позаботиться здесь? Если да, то как я могу гарантировать, что входящий файл кодируется UTF-8? –

0

Если вы используете Обще-FileUpload LIB и использовать его в потоковом режиме (docs here), вы никогда не будете держать больше входящего файла в памяти, чем вы хотите. По мере того, как запрос поступает от клиента, и вы выполняете итерацию по каждому элементу, вы получаете InputStream для каждого поля формы или загружаете файл и можете делать все, что хотите, с помощью InputStream, например, записывать его в файл (и в том числе отбрасывать исключение если пользователь попытался загрузить, скажем, файл размером 2 ГБ, когда ваш лимит составляет 20 МБ или что-то еще).

Единственным недостатком использования API потоковой передачи commons-fleupload является то, что обработка регулярных полей формы также должна выполняться через InputStream, но это легко сделать с вызовом Streams.asString().

+0

Не могли бы вы поместить код для потокового вещания commons-fileupload? Когда я делаю file.inputStream, это не то, что вы имеете в виду? Также я обновил свой пост, второй вариант лучше? –

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