Как поместить файлы в zip только для их упаковки и не сжимать их в Java

Есть ли способ в Java упаковать файлы в zip без сжатия? Мне просто нужно упаковать много файлов в один, но мне нужно быстро, а сжатие занимает много времени. Я попробовал что-то вроде метода Stored ZipOutputStream, но результат всегда поврежден. Кто-нибудь знает какое-то решение?

Обновлено: Вот мой код:

response.setContentType("application/zip"); // zip archive format
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment()
                                                                            .filename("download.zip", StandardCharsets.UTF_8)
                                                                            .build()
                                                                            .toString());
        
            response.setContentLengthLong(totalSize);
    
            try(ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) {
                zipOutputStream.setLevel(Deflater.NO_COMPRESSION);
            for (FileSystemResource file : resources) {
                try (InputStream inputStream = file.getInputStream()) {
                    zipOutputStream.putNextEntry(new ZipEntry(file.getFilename().toString()));
                    StreamUtils.copy(inputStream, zipOutputStream);
                    zipOutputStream.flush();
                }
            }
        }

он работает нормально, но когда я добавил:

zipOutputStream.setLevel(Deflater.NO_COMPRESSION);

я получаю эту ошибку, когда пытаюсь открыть финальный почтовый индекс: Не удалось открыть, процесс ERROR 1 не существует

Zip без уровня всегда хорошо

Может быть, взгляните на это и это

g00se 12.06.2023 16:44

Пожалуйста, покажите свой код.

vanje 12.06.2023 16:46

поскольку вы отправляете только один файл и, похоже, не хотите сжатия, почему вы все равно вставляете файл в zip-файл?

jtahlborn 12.06.2023 22:18
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
53
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать zipOutputStream.setLevel(Deflater.NO_COMPRESSION).

Метод setLevel ZipOutputStream — это то, что вам нужно. Значение «0» указывает отсутствие сжатия.

https://docs.oracle.com/javase/8/docs/api/java/util/zip/ZipOutputStream.html#setLevel-int-

Обновлено: лучшая форма - использовать константу-дефлятор NO_COMPRESSION вместо 0.

https://docs.oracle.com/javase/8/docs/api/java/util/zip/Deflater.html#NO_COMPRESSION

Проще, да, но не используйте магические числа, а это (или эквивалент).

g00se 12.06.2023 16:58

Совершенно верно, документация для setLevel не ссылается на константы, но документирует, что значение представляет собой число от 0 до 9. В любом случае, вот документация по константе «NO_COMPRESSION»: docs.oracle.com/javase /8/docs/api/java/util/zip/…

Adam Wise 12.06.2023 19:57

Посмотрите на мой отредактированный пост, я попробовал setLevel, но все еще есть проблемы

Sizor 12.06.2023 20:13

Если этот параметр utf-8 в ответе применяется к файлу, у вас будут проблемы. Файл будет поврежден

g00se 12.06.2023 21:11
Ответ принят как подходящий

Проблема в том, что вы устанавливаете длину содержимого ответа (предположительно) на длину файла, который вы выводите. однако zip-файл, даже без сжатия, по-прежнему включает заголовок (или нижний колонтитул, в зависимости от обстоятельств). вам нужно либо вычислить длину всего zip-файла, либо использовать фрагментированное кодирование.

Это может объяснить, почему это работает, если сжатие включено — общая длина zip-файла будет немного больше, чем исходный файл, если нет сжатия, но меньше, если сжатие есть. Без сжатия файл будет усечен из-за вызова setContentLength. Попробуйте вызвать setContentLength в конце с фактической длиной заархивированного файла/потока вывода.

Adam Wise 13.06.2023 17:09

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

jtahlborn 13.06.2023 17:16

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

Sizor 14.06.2023 10:53

@Sizor это то, для чего предназначена кодировка по частям. Вам не нужно знать размер перед отправкой. в качестве альтернативы вы можете пропустить zip-упаковку и просто отправить файл напрямую.

jtahlborn 14.06.2023 16:02

Другие вопросы по теме