2013-05-24 2 views
4

Я разработал простую медиабиблиотеку, где вы можете выбрать набор изображений и загрузить их. Когда клиент запрашивает загрузку, сервлет получает ключи blob для использования для создания zip-файла, а затем запускается Task для процедурыGoogle Appengine JAVA - Zip много сбережений изображений в Blobstore

Задача итерации по полученным клавишам blob и zip изображения в архив. Когда задача завершится, пользователю будет отправлено письмо с ссылкой для загрузки.

Вот моя проблема:

FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock); 
OutputStream blobOutputStream = Channels.newOutputStream(writeChannel); 
ZipOutputStream zip = new ZipOutputStream(blobOutputStream); 

Один канал может обрабатывать только такое количество байтов

BlobstoreService.MAX_BLOB_FETCH_SIZE

Из-за этого, я должен открыть и закрыть канал каждые 1 мб данных, которые я должен написать (тот же вопрос для чтения, но для чтения я использовал this code, и он работает). или метод записи() генерирует исключения нулевого

Открытие и закрытие канала с нормальным OutputStream, не проблема представляет, как this code

Но обработка в Zip файл я также управлять

ZipOutputStream zip = new ZipOutputStream(blobOutputStream); 
ZipEntry zipEntry = new ZipEntry(image_file_name); 
zipOut.putNextEntry(zipEntry); 
// while the image has bytes to write 
    zipOut.write(bytesToWrite); 

После того, как я написал 1MB данных в ZipEntry, мне нужно закрыть канал и снова открыть его.

Так вот проблема: где я открываю новый канал, я не могу получить доступ к предыдущей zipEntry, которую я писал, а затем я не могу продолжать писать следующий 1 Мб изображения, которое обрабатываю.

И, после того, как новый канал, если я стараюсь писать на объекте ZipEntry (без повторной инициализации) я получаю исключение ClosedChannel

Here пример кода я написал, я знаю, не работает, но объясняет, что я пытаюсь сделать.

Мой вопрос тогда: Как (если возможно, вне курса) могу ли я создать почтовый файл, записывающий 1 МБ за раз?

Я также другие подходы, вещь мне нужно, чтобы пронестись несколько изображений в один почтовый индекс и сохранить его в Blobstore, если у вас есть другие идеи, чтобы сделать это, пожалуйста, скажите мне

+0

Страницы, которые я уже читал: http://jsfiddle.net/KVprB/ –

+0

Как-то вы должны использовать буферизованное чтение, например http://stackoverflow.com/questions/4308276/how-to-zip-a-file- в то время как-пишет-к-это предлагает. Этот пример относится к другим типам потоков, но может применяться основной принцип. Я полагаю, что замыкание между записями - это нечто, чего можно избежать, и этот буферизированный читатель в смеси сделает этот камень. – mico

+0

У меня нет никаких проблем с чтением Blob. Моя проблема в том, когда я пишу zip-файл. Поскольку я могу писать только 1 МБ на канал, мне нужен способ сохранить «ZipEntry», когда я закрываю и открываю новый канал –

ответ

2

Вы должны создайте собственный поток, который может управлять каналами. Когда достигается ограничение размера капли, ваш поток закрывает текущий канал и открывает новый.

Пример для локальных файлов:

public class ZipChannels { 
public static void main(String[] args) throws IOException { 
    File dirToZip = new File("target\\dependency"); 

    //create zip-files 
    ChannelOutput out = new ChannelOutput(); 
    ZipOutputStream zip = new ZipOutputStream(out); 
    int b = 0; 
    for(File file: dirToZip.listFiles()) { 
     ZipEntry zipEntry = new ZipEntry(file.getName()); 
     zip.putNextEntry(zipEntry); 
     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); 
     while((b = bis.read()) != -1) { 
      zip.write(b); 
     } 
     bis.close(); 
     zip.closeEntry(); 
    } 
    zip.close(); 

    //merge all into one file for check it 
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("package_all.zip")); 
    for (int i = 0; i < out.getChannelCount(); i++) { 
     BufferedInputStream bis = new BufferedInputStream(new FileInputStream("package_" + i + ".zip")); 
     while((b = bis.read()) != -1) { 
      bos.write(b); 
     } 
     bis.close(); 
    } 
    bos.close(); 
} 

public static class ChannelOutput extends OutputStream { 
    private OutputStream channel; 
    private int count = 0; 
    final private int MAX = 1000000; 

    @Override 
    public void write(int b) throws IOException { 
     if(count++ % MAX == 0) { 
      openNewChannel(); 
     } 
     channel.write(b); 
    } 

    protected void openNewChannel() throws IOException { 
     if(channel != null) { 
      channel.close(); 
     } 
     channel = new BufferedOutputStream(new FileOutputStream("package_" + (count/MAX) + ".zip")); 
    } 
    public int getChannelCount() { 
     return count/MAX + 1; 
    } 

    @Override 
    public void close() throws IOException { 
     channel.close(); 
    } 
    @Override 
    public void flush() throws IOException { 
     channel.flush(); 
    } 
} 
} 

Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь спрашивать.

Смежные вопросы