Скачать большие файлы с помощью InputStream - PullRequest
0 голосов
/ 21 ноября 2019

У нас есть сервер Weblogic, работающий в Linux с несколькими управляемыми серверами. Максимальный размер кучи управляемого сервера, которым я занимаюсь, составляет 1024 МБ. На этом сервере развернуто несколько приложений. Одно из этих приложений обрабатывает ответ от API REST для загрузки файлов размером до 250 МБ. Для файлов размером более 50 МБ иногда не возникает проблем, но иногда происходит сбой сервера с ошибкой OOM. Вот мой код:

Client client = Client.create();          
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
            throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
        }
String output = response.getEntity(String.class);
byte[] fileContent = Base64.decodeBase64(output.getBytes());
if (fileContent != null) {
        OutputStream out = null;
        try {
            res.reset();
            out = res.getOutputStream();
            res.setContentType(contentType);
            res.setHeader("Content-Disposition", "inline; filename=" + fileName + "; size=" + String.valueOf(fileContent.length));
            res.setContentLength(fileContent.length);
            out.write(fileContent);
        } catch (Exception ex) {
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
        }
    } 

Поскольку были проблемы с памятью, я попытался использовать подход InputStream. Ниже приведен измененный код:

Client client = Client.create();          
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
        throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
    }
InputStream source = response.getEntityInputStream(); // IS THIS OKAY?

if (source!= null) {
        OutputStream out = null;
        int count = 0;
        try {
            byte[] buffer = new byte[1024];
            int read = 0;
            res.reset();
            res.setContentType(contentType);
            res.setHeader("Content-Disposition", "inline; filename=" + fileName);
            out = res.getOutputStream();
            while ((read = source.read(buffer)) != -1) {
                out.write(buffer, 0, read);
                count++;
            }                
            System.out.println("COUNT: " + count);// For a 60MB file, this prints 86000. why?
        } catch (Exception ex) {
            e.printStackTrace();
        }finally{
            out.flush();
            out.close();
            source.close();
        }

Этот код не работает в OOM, но файл не загружается / поврежден. Связана ли проблема с тем, что это ответ в кодировке Base64, и я не обрабатываю его должным образом? Если да, что мне делать? Приложение работает на Java 7. Мой подход использует InputStream для решения OOM, хорошо? Служба не отправляет ответ кусками. Какие еще пути я мог бы пойти дальше? Я беспокоюсь, что я сталкиваюсь с ошибками (не всегда) только для 50 МБ файла. Сервер является удаленным и обрабатывается другой группой. Как я могу проверить, есть ли другие причины, ответственные за сбои сервера?

Ответы [ 2 ]

0 голосов
/ 25 ноября 2019

Я использовал Base64InputStream для декодирования ответа InputStream, и он работал нормально.

InputStream stream = response.getEntityInputStream();
Base64InputStream bis = new Base64InputStream(stream);

Затем использовал bis для записи файла. Этот подход теперь печатает переменную count около 65000.

0 голосов
/ 21 ноября 2019

Привет Попробуйте это руководство вместо этого. https://www.baeldung.com/java-download-file

Это фантастический сайт, который предлагает множество руководств по Java практически для всех мыслимых сценариев.

Удачи! : -)

...