2013-05-24 1 views
4

이미지 세트를 선택하여 다운로드 할 수있는 간단한 미디어 라이브러리를 개발했습니다. 클라이언트가 다운로드를 요청하면 서블릿은 zip 파일 만들기에 사용할 BLOB 키를 수신 한 다음 절차에 대해 작업을 시작합니다.Google Appengine JAVA - 많은 이미지를 Blobstore에 저장합니다.

받은 BLOB 키를 반복하여 이미지를 아카이브로 압축합니다. 작업이 완료되면 다운로드 링크가있는 메일이 사용자에게 전송됩니다. 내가 열고 닫아야합니다,

BlobstoreService.MAX_BLOB_FETCH_SIZE 때문에 그

하나의 채널은 바이트 만이 양을 처리 할 수 ​​

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

: 여기

내 문제입니다 채널마다 1MB의 데이터를 작성해야합니다 (동일한 문제는 읽기 용이지만, 사용 된 읽기는 this code이며 작동합니다). 또는 쓰기() 메소드는 this code

처럼, 널 예외에게 선물 문제

열기 및 정상의 OutputStream으로 채널을 폐쇄하지 않는 발생하지만 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); 

ZipEntry에 1MB의 데이터를 쓴 후에는 채널을 닫고 다시 열어야합니다.

그래서 여기에 문제가 있습니다. 내가 새 채널을 열면 전의 zipEntry에 액세스 할 수 없으며 작성 중이므로 다음 1MB의 이미지를 계속 처리 할 수 ​​없습니다. 내가 ZipEntry를 객체에 작성하려고하면

는 그리고, 오픈 새로운 채널 후, (W를 다시 초기화 O /) 내가 아는,

Here 내가 쓴 샘플 코드 인 ClosedChannel 예외를 얻을 작동하지 않습니다,하지만 내가 뭘하려고하는지 설명합니다.

내 질문에 : 어떻게 (가능하다면, 물론) 내가 시간당 1MB를 작성하는 zip 파일을 만들 수 있습니까? 당신이 할 수있는 다른 아이디어가 있다면 나는 또한 다른 방법을 사용할 수있어

는, 내가 필요로하는 것은 지퍼로 일부 이미지를 압축하여 Blob 저장소에 저장하는 것입니다, 당신은해야 나에게

+0

페이지를 이미 읽어 http://jsfiddle.net/KVprB/을 –

+0

은 어떻게 든 당신이 http://stackoverflow.com/questions/4308276/how-to-zip-a-file-처럼, 버퍼링 된 읽기를 사용한다 쓰기 - 그것이 - 그것이 제안하는 동안. 이 예제는 다른 유형의 스트림이지만 주요 원칙이 적용될 수 있습니다. 필자와 필자 사이의 밀접한 관계는 피해야 만하고 버퍼링 된 독자가이 락을 만들 것이라고 생각합니다. – mico

+0

Blob을 읽는 데 전혀 문제가 없습니다. 내 문제는 내가 zip 파일을 쓸 때이다. 채널 당 1MB 만 쓸 수 있기 때문에 새 채널을 닫고 열 때 "ZipEntry"를 유지하는 방법이 필요합니다. –

답변

2

을 알려주세요 채널을 조작 할 수있는 스트림을 만듭니다. BLOB 크기 제한에 도달하면 스트림이 현재 채널을 닫고 새 채널을 엽니 다. 로컬 파일에 대한

예 : 당신은 질문이있는 경우

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(); 
    } 
} 
} 

가, 물어 주시기 바랍니다.