2010-02-19 46 views
1

我試圖讓Tomcat寫出servlet的內容作爲bzip2文件(也許愚蠢的要求,但它顯然是一些集成工作的必要條件)。我正在使用Spring框架,因此它在AbstractController中。寫文件數據爲Bzip2輸出servlet響應

我使用的bzip2庫從http://www.kohsuke.org/bzip2/

我能得到的內容bzip2壓縮的很好,但是當文件被寫入了它似乎包含了一堆元數據,是無法辨認的bzip2的文件。

下面是我在做什麼

// get the contents of my file as a byte array 
byte[] fileData = file.getStoredFile(); 

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

//create a bzip2 output stream to the byte output and write the file data to it    
CBZip2OutputStream bzip = null; 
try { 
    bzip = new CBZip2OutputStream(baos); 
    bzip.write(fileData, 0, fileData.length); 
    bzip.close(); 
} catch (IOException ex) { 
    ex.printStackTrace(); 
} 
byte[] bzippedOutput = baos.toByteArray(); 
System.out.println("bzipcompress_output:\t" + bzippedOutput.length); 

//now write the byte output to the servlet output 
//setting content disposition means the file is downloaded rather than displayed 
int outputLength = bzippedOutput.length; 
String fileName = file.getFileIdentifier(); 
response.setBufferSize(outputLength); 
response.setContentLength(outputLength); 
response.setContentType("application/x-bzip2"); 
response.setHeader("Content-Disposition", 
             "attachment; filename="+fileName+";)"); 

這是正在從春天下面的方法稱爲一個AbstractController

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception 

我它在不同的做法採取一些刺,包括直接寫入ServletOutput,但我非常難過,無法在網上找到任何/很多的例子。

來自任何人遇到此問題的任何建議將不勝感激。替代庫/方法很好,但不幸的是它必須是bzip2'd。

回答

3

發佈的方法確實很奇怪。我已經重寫過,所以它更有意義。試一試。

String fileName = file.getFileIdentifier(); 
byte[] fileData = file.getStoredFile(); // BTW: Any chance to get this as InputStream? This is namely memory hogging. 

response.setContentType("application/x-bzip2"); 
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); 

OutputStream output = null; 

try { 
    output = new CBZip2OutputStream(response.getOutputStream()); 
    output.write(fileData); 
} finally { 
    output.close(); 
} 

你看,只是包裝與CBZip2OutputStream響應的輸出流和寫入byte[]它。

在服務器日誌中,您可能碰巧看到IllegalStateException: Response already committed(隨着下載的正確發送),那麼這意味着Spring正在嘗試轉發請求/響應。我不做春天,所以我不能詳細介紹,但你至少應該指示春天到遠離從響應。不要讓它做一個映射,向前或其他。我認爲返回null就足夠了。

+0

+1用於可能的IllegalStateException的早期警告。 – 2010-02-20 06:21:13

2

您可能會發現與CompressorStreamFactorycommons-compress更容易一些。它是你已經使用的Ant版本的一個死角,並且最終有兩行不同於BalusC的例子。

或多或少都是圖書館偏好的問題。

OutputStream out = null; 
try { 
    out = new CompressorStreamFactory().createCompressorOutputStream("bzip2", response.getOutputStream()); 
    IOUtils.copy(new FileInputStream(input), out); // assuming you have access to a File. 
} finally { 
    out.close(); 
}