Есть ли способ в 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 без уровня всегда хорошо
Пожалуйста, покажите свой код.
поскольку вы отправляете только один файл и, похоже, не хотите сжатия, почему вы все равно вставляете файл в zip-файл?
Вы можете использовать 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
Проще, да, но не используйте магические числа, а это (или эквивалент).
Совершенно верно, документация для setLevel не ссылается на константы, но документирует, что значение представляет собой число от 0 до 9. В любом случае, вот документация по константе «NO_COMPRESSION»: docs.oracle.com/javase /8/docs/api/java/util/zip/…
Посмотрите на мой отредактированный пост, я попробовал setLevel, но все еще есть проблемы
Если этот параметр utf-8 в ответе применяется к файлу, у вас будут проблемы. Файл будет поврежден
Проблема в том, что вы устанавливаете длину содержимого ответа (предположительно) на длину файла, который вы выводите. однако zip-файл, даже без сжатия, по-прежнему включает заголовок (или нижний колонтитул, в зависимости от обстоятельств). вам нужно либо вычислить длину всего zip-файла, либо использовать фрагментированное кодирование.
Это может объяснить, почему это работает, если сжатие включено — общая длина zip-файла будет немного больше, чем исходный файл, если нет сжатия, но меньше, если сжатие есть. Без сжатия файл будет усечен из-за вызова setContentLength. Попробуйте вызвать setContentLength в конце с фактической длиной заархивированного файла/потока вывода.
да, я тоже этого ожидаю. обычно вы не можете вызывать setContentLength после отправки данных, потому что это нужно сначала отправить в виде заголовка. если данные малы, в зависимости от используемой вами библиотеки, они могут буферизоваться в элементе перед отправкой. но если он большой, вы бы не хотели этого делать.
Итак, я проверил это, и у вас есть правда. Это потому, что установка немного меньшего размера, чем окончательный почтовый индекс. Проблема в том, что мои файлы не настолько малы, чтобы просто упаковать их перед отправкой и отправить, мне нужно, чтобы они сразу отправлялись в ответ, но тогда я не буду знать размер моего индикатора выполнения бэкэнда, я думаю, что я потерян: D
@Sizor это то, для чего предназначена кодировка по частям. Вам не нужно знать размер перед отправкой. в качестве альтернативы вы можете пропустить zip-упаковку и просто отправить файл напрямую.
Может быть, взгляните на это и это