Подтвердить что ты не робот

Как загрузить большие файлы без проблем с памятью в java

Когда я пытаюсь загрузить большой файл с 260 МБ с сервера, я получаю эту ошибку: java.lang.OutOfMemoryError: Java heap space. Я уверен, что размер кучи меньше 252 МБ. Есть ли способ загрузить большие файлы без увеличения размера кучи?

Как я могу загрузить большие файлы без этой проблемы? Мой код приведен ниже:

String path= "C:/temp.zip";   
response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\""); 
byte[] buf = new byte[1024];   
try {   

             File file = new File(path);   
             long length = file.length();   
             BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));   
             ServletOutputStream out = response.getOutputStream();   

             while ((in != null) && ((length = in.read(buf)) != -1)) {   
             out.write(buf, 0, (int) length);   
             }   
             in.close();   
             out.close();
4b9b3361

Ответ 1

Есть 2 места, где я вижу, что вы потенциально можете наращивать использование памяти:

  • В буфере, читающем ваш входной файл.
  • В буфере, записывающем в выходной поток (HTTPOutputStream?)

Для # 1 я предлагаю прочитать непосредственно из файла через FileInputStream без BufferedInputStream. Попробуйте это первым и посмотрите, разрешит ли он вашу проблему. то есть:

FileInputStream in = new FileInputStream(file);   

вместо:

BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));   

Если # 1 не решит проблему, вы можете периодически периодически промывать выходной поток после того, как будет записано столько данных (при необходимости уменьшите размер куска):

т

try
{
    FileInputStream fileInputStream  = new FileInputStream(file);
    byte[] buf=new byte[8192];
    int bytesread = 0, bytesBuffered = 0;
    while( (bytesread = fileInputStream.read( buf )) > -1 ) {
        out.write( buf, 0, bytesread );
        bytesBuffered += bytesread;
        if (bytesBuffered > 1024 * 1024) { //flush after 1MB
            bytesBuffered = 0;
            out.flush();
        }
    }
}
finally {
    if (out != null) {
        out.flush();
    }
}

Ответ 2

К сожалению, вы не указали, какой тип out. Если у вас проблемы с памятью, я думаю, что это ByteArrayOutpoutStream. Итак, замените его на FileOutputStream и напишите байт, который вы загружаете напрямую в файл.

BTW, не используйте метод read(), который читает байты. Вместо этого используйте read(byte[] arr). Это намного быстрее.

Ответ 3

Сначала вы можете удалить (in!= null) из своего оператора while, это необязательно. Во-вторых, попробуйте удалить BufferedInputStream и просто выполните:

FileInputStream in = new FileInputStream(file);

Ответ 4

Нет ничего плохого (в отношении использования памяти) с кодом, который вы показываете. Контейнер сервлета сконфигурирован для буферизации всего ответа (см. Конфигурацию web.xml) или утечка памяти в другом месте.