2012/09/16

[心得] Apache Common Compress - ZipAchieveStream

資料的壓縮存儲,對於資訊傳遞的最大價值,在於提供了一種將資料化繁為簡,暗示了「這是所有相關內容」的一種行為。而在壓縮行為的歷史上,各種壓縮程式的䦕發競賽中,有時流行比較速度,有時流行壓縮比,而最不被提及的,則是資料加密的安全度,雖然感覺是最重要的,但卻是最少被使用者提及的。當雲端儲存供應商欲提供使用者此相關功能時,如何能針對上述三項著眼點進行彈性的選擇設定,就成了實作上的一個重要課題。

而Apache Common Compress為了Java程式開發者提供了最便利的解決途徑,它除了提供目前常用壓縮格式之IOStream介面及實作外,亦提供了原本JDK壓縮物件中支援不甚完善的編碼設定解決之道,當然也提供了壓縮率及加密的設定實作。

以下程式碼主要示意如何在servlet中,利用Apache Httpclient以及ZipAchieveStream將檔案http串流經過壓縮輸出,紅字部分為自定參數。


/** Handle File Name **/
String userAgent = request.getHeader("User-Agent");
String filename = request.getParameter("filename");  // .zip file name

if (userAgent.contains("MSIE")) {
    filename = java.net.URLEncoder.encode(filename, "utf-8");
    filename = filename.replace("+", "%20");
}

response.setHeader( "Content-Disposition", "attachment; filename=\"" + new String(filename.getBytes("utf-8"), "ISO8859_1" ) + "\"");

/** Handle Zip Compress and output **/
response.setContentType("application/zip");
response.setCharacterEncoding("UTF-8");

ServletOutputStream sOut = response.getOutputStream();
ZipArchiveOutputStream zout = new ZipArchiveOutputStream(sOut); 

HttpClient httpClient = new HttpClient();

GetMethod getMethod = new GetMethod(sourceURL);
getMethod.setFollowRedirects(false);     
httpClient.executeMethod(getMethod);
if(getMethod.getStatusCode() != 200){
    continue;
}
InputStream is = getMethod.getResponseBodyAsStream();

ZipArchiveEntry zipEntry = new ZipArchiveEntry(sourceFilename,"UTF-8"));
zout.putArchiveEntry(zipEntry);
zout.setEncoding("UTF-8");

int length;
while((length = is.read(buffer) > 0){
    zout.write(buffer, 0, length);
}
zout.closeArchiveEntry();
is.close();
zout.close();
response.flushBuffer();// http response

說穿了,這程式片段就是做了水管工的工作而已,相當的容易理解。如果你試著修改了但是無法運作,那麼一定是因為是我把對資料夾的遞迴壓縮,為了範例簡化為單檔壓縮的緣故,請努力循著debug流程就可以解決,如果真的有不明白為什麼要這樣寫的部份,歡迎留言詢問,我有心就會回覆的。

1 comment:

有什麼想說的嗎?

肉包

小明總是在住家附近的肉包店買肉包,20 年來,肉包從一顆 10 元漲到一顆 30 元,從一天可以吃三顆,到一天只能吃一顆,今天他心血來潮問了老闆為何這些年漲了這麼多,老闆很驕傲地回答... 「這區的店租漲價了啊!然後你沒發現我們現在店面不但有冷氣,又有座位,還有 80"...