[英]Decompressing a large blob in java on Google App Engine
我正在使用Java(JDO)在Google App Engine上構建一些東西。 我用編程方式用Deflater壓縮一個大字節[],然后像在blobstore中一樣存儲壓縮的byte []。 這非常有效:
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);
}
}
在我的Functions類中使用static compress()和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));
有關如何最好地從blobstore獲取壓縮HTML,解壓縮並顯示它的任何想法? 即使我需要將它傳遞給任務隊列並在顯示進度條時輪詢完成 - 這沒關系。 我真的不在乎,只要它有效並最終發揮作用。 我很感激您可以在這里與我分享任何指導。
謝謝你的幫助。
你可以查看運行異步的RequestBuilder
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());
}
我接受了尼克約翰遜的想法,並直接從Blobstore讀取服務blob。 現在它閃電般快! 這是代碼:
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類: 讀取BlobstoreInputStream> = 1MB大小
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.