【问题标题】:Write file data as Bzip2 to output of servlet response将文件数据作为 Bzip2 写入 servlet 响应的输出
【发布时间】:2011-01-18 23:26:14
【问题描述】:

我正在尝试让 Tomcat 将 servlet 内容写为 bzip2 文件(这可能是愚蠢的要求,但对于某些集成工作显然是必要的)。我使用的是 Spring 框架,所以它位于 AbstractController 中。

我正在使用来自 http://www.kohsuke.org/bzip2/ 的 bzip2 库

我可以很好地获得内容 bzip,但是当文件被写出时,它似乎包含一堆元数据并且无法识别为 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+";)");

这是从 Spring 抽象控制器中的以下方法调用的

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

我用不同的方法尝试了一些方法,包括直接写入 ServletOutput,但我很困惑,在网上找不到任何/很多示例。

非常感谢之前遇到过此问题的任何人的任何建议。替代库/方法很好,但不幸的是它必须是 bzip2'd。

【问题讨论】:

    标签: java spring servlets compression bzip2


    【解决方案1】:

    张贴的方法确实很奇怪。我已经重写,以便更有意义。试一试。

    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 正在尝试转发请求/响应。我不做 Spring,所以我不能详细说明,但你至少应该指示 Spring 远离响应。不要让它做一个映射,转发或其他什么。我认为返回null 就足够了。

    【讨论】:

    • +1 表示可能的 IllegalStateException 的早期警告。
    【解决方案2】:

    您可能会发现使用来自commons-compressCompressorStreamFactory 会更容易一些。它是您已经在使用的 Ant 版本的后继版本,并且与 BalusC 的示例有 2 行不同。

    或多或少是图书馆偏好的问题。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-10
      • 1970-01-01
      相关资源
      最近更新 更多