Эффективный поток Zip-файлов в Java - PullRequest
1 голос
/ 09 октября 2019

Проблема

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

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

Попытка решения

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

1 Ответ

1 голос
/ 11 октября 2019

Вы можете передавать большой zip-файл напрямую через HTTP-соединение.

java.util.zip.ZipOutputStream позволяет заархивировать данные непосредственно в поток без промежуточного хранилища.

Ниже приведен фрагмент записи набора ссылок на файлы вПоток в виде zip-архива.

Причиной для потоковой передачи 5 ГБ может потребоваться настройка времени ожидания и пула потоков вашего контейнера сервлета.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipStreamer {

    public void streamZip(OutputStream os, Iterable<FileLink> entries) throws IOException {
        ZipOutputStream zos = new ZipOutputStream(os);
        for(FileLink e: entries) {

            ZipEntry entry = new ZipEntry(e.getName());
            File file = e.getFile();
            entry.setTime(file.lastModified());
            zos.putNextEntry(entry);
            if (file.isFile()) {
                copyBytes(zos, new FileInputStream(file));
            }
            zos.closeEntry();
        }
        zos.close();
    }

    private static void copyBytes(OutputStream dest, InputStream source) {
        // copy data between streams
    }

    public interface FileLink {

        public String getName();

        public File getFile();
    }
}
...