2011-09-21 49 views
3

我在Java(JDO)中的Google App Engine上構建了一些東西。我用Deflater以編程方式壓縮大字節[],然後將壓縮字節[]存儲在blobstore中。這個偉大的工程:在Google App Engine上解壓Java中的大塊blob

public class Functions { 

public static byte[] compress(byte[] input) throws UnsupportedEncodingException, IOException, MessagingException 
    { 

     Deflater df = new Deflater();  //this function mainly generate the byte code 
     df.setLevel(Deflater.BEST_COMPRESSION); 
     df.setInput(input); 

     ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length); //we write the generated byte code in this array 
     df.finish(); 
     byte[] buff = new byte[1024]; //segment segment pop....segment set 1024 
     while(!df.finished()) 
     { 
      int count = df.deflate(buff);  //returns the generated code... index 
      baos.write(buff, 0, count);  //write 4m 0 to count 
     } 
     baos.close(); 

     int baosLength = baos.toByteArray().length; 
     int inputLength = input.length; 
     //System.out.println("Original: "+inputLength); 
     // System.out.println("Compressed: "+ baosLength); 

     return baos.toByteArray(); 

    } 

public static byte[] decompress(byte[] input) throws UnsupportedEncodingException, IOException, DataFormatException 
    { 

     Inflater decompressor = new Inflater(); 
     decompressor.setInput(input); 

     // Create an expandable byte array to hold the decompressed data 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length); 

     // Decompress the data 
     byte[] buf = new byte[1024]; 
     while (!decompressor.finished()) { 
      try { 
       int count = decompressor.inflate(buf); 
       bos.write(buf, 0, count); 
      } catch (DataFormatException e) { 
      } 
     } 
     try { 
      bos.close(); 
     } catch (IOException e) { 
     } 

     // Get the decompressed data 
     byte[] decompressedData = bos.toByteArray(); 

     return decompressedData; 


    } 

public static BlobKey putInBlobStore(String contentType, byte[] filebytes) throws IOException { 

     // Get a file service 
      FileService fileService = FileServiceFactory.getFileService(); 


      AppEngineFile file = fileService.createNewBlobFile(contentType); 

      // Open a channel to write to it 
      boolean lock = true; 
      FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock); 

      // This time we write to the channel using standard Java 
      BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(filebytes)); 
      byte[] buffer; 
      int defaultBufferSize = 524288; 
      if(filebytes.length > defaultBufferSize){ 
       buffer = new byte[defaultBufferSize]; // 0.5 MB buffers 
      } 
      else{ 
       buffer = new byte[filebytes.length]; // buffer the size of the data 
      } 

      int read; 
      while((read = in.read(buffer)) > 0){ //-1 means EndOfStream 
       System.out.println(read); 
       if(read < defaultBufferSize){ 
        buffer = new byte[read]; 
       } 
       ByteBuffer bb = ByteBuffer.wrap(buffer); 
       writeChannel.write(bb); 
      } 
      writeChannel.closeFinally(); 

     return fileService.getBlobKey(file); 
    } 
} 

使用靜態壓縮()和putInBlobStore()函數在我的函數類的,我可以壓縮並存儲一個byte []像這樣:

BlobKey dataBlobKey = Functions.putInBlobStore("MULTIPART_FORM_DATA", Functions.compress(orginalDataByteArray)); 

非常甜蜜。我真的在挖GAE。

但現在,問題:

我存儲壓縮的HTML我想檢索和解壓的飛行在JSP頁面中的iframe中顯示哪些。壓縮很快,但減壓需要永遠!即使壓縮的HTML是15k,有時解壓縮也會死掉。

這裏是我的減壓方法:

URL file = new URL("/blobserve?key=" + htmlBlobKey); 
     URLConnection conn = file.openConnection(); 
     conn.setReadTimeout(30000); 
     conn.setConnectTimeout(30000); 
     InputStream inputStream = conn.getInputStream(); 
     byte[] data = IOUtils.toByteArray(inputStream); 
     return new String(Functions.decompress(data)); 

就如何最好地採取壓縮HTML從Blob存儲,解壓縮和顯示它有什麼想法?即使我需要將它傳遞給任務隊列並在顯示進度條時輪詢完成,那也沒關係。我真的不在乎,只要它是有效的,並最終運作。感謝您在這裏與我分享的任何指導。

感謝您的幫助。

+0

是延遲肯定是在減壓?你有沒有檢查輸出壓縮的檢索數據,看看它是否同樣緩慢? –

+0

你爲什麼從自己那裏獲取blob?爲什麼不使用blob讀取API? –

+0

另外,爲什麼您將數據存儲在blobstore中進行壓縮,給定了額外的延遲時間呢? –

回答

0

我把尼克·約翰遜的想法,並從Blob存儲VS直接服務於斑點閱讀RequestBuilder。現在它閃電般快!下面的代碼:

try{ 
     ChainedBlobstoreInputStream inputStream = new ChainedBlobstoreInputStream(this.getHtmlBlobKey()); 
     //StringWriter writer = new StringWriter(); 
     byte[] data = IOUtils.toByteArray(inputStream); 
     return new String(Functions.decompress(Encrypt.AESDecrypt(data))); 
     //return new String(data); 
    } 
    catch(Exception e){ 
      return "No HTML Version"; 
     } 

我得到了ChainedBlobstoreInputStream類從這裏: Reading a BlobstoreInputStream >= 1MB in size

0

你可以看看它運行的異步

RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET,"/blobserve?key=" + htmlBlobKey); 
try { 
requestBuilder.sendRequest(null, new RequestCallback() { 
public void onError(Request request, Throwable exception) { 
    GWT.log(exception.getMessage()); 
} 
public void onResponseReceived(Request request, Response response) { 
    doSomething(response.getText());//here update your iframe and stop progress indicator 
} 
}); 
} catch (RequestException ex) { 
    GWT.log(ex.getMessage()); 
} 
+0

非常酷。我明天再試試看,並用我的發現更新這篇文章。謝謝Sasha! – Bob