Я использую IBM Websphere Application Server v6 и Java 1.4 и пытаюсь записать большие файлы CSV в ServletOutputStream
для загрузки пользователем. В настоящее время размер файлов составляет 50-750 МБ.
Меньшие файлы не вызывают слишком много проблем, но с более крупными файлами кажется, что он записывается в кучу, которая затем вызывает ошибку OutOfMemory и сбрасывает весь сервер.
Эти файлы могут обслуживаться только для аутентифицированных пользователей через HTTPS, поэтому я обслуживаю их через Servlet, а не просто вставляя их в Apache.
Используемый мной код (некоторый пух удаляется вокруг этого):
resp.setHeader("Content-length", "" + fileLength);
resp.setContentType("application/vnd.ms-excel");
resp.setHeader("Content-Disposition","attachment; filename=\"export.csv\"");
FileInputStream inputStream = null;
try
{
inputStream = new FileInputStream(path);
byte[] buffer = new byte[1024];
int bytesRead = 0;
do
{
bytesRead = inputStream.read(buffer, offset, buffer.length);
resp.getOutputStream().write(buffer, 0, bytesRead);
}
while (bytesRead == buffer.length);
resp.getOutputStream().flush();
}
finally
{
if(inputStream != null)
inputStream.close();
}
FileInputStream
, похоже, не вызывает проблемы, так как если я пишу в другой файл или просто полностью удаляю запись, использование памяти не представляется проблемой.
Я думаю, что resp.getOutputStream().write
хранится в памяти до тех пор, пока данные не будут отправлены клиенту. Таким образом, весь файл может быть прочитан и сохранен в resp.getOutputStream()
, что вызовет проблемы с памятью и сбой!
Я попытался Буферизировать эти потоки, а также попытался использовать Каналы из java.nio
, ни одна из которых, похоже, не имеет никакого отношения к проблемам с моей памятью. Я также сбросил OutputStream
один раз за итерацию цикла и после цикла, что не помогло.