java - 将文件数据作为 Bzip2 写入 servlet 响应的输出

标签 java spring servlets compression bzip2

我试图让 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 抽象 Controller 中的以下方法调用的

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

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

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

最佳答案

发布的方法确实很奇怪。我重写了它,使它更有意义。试一试。

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 就足够了。

关于java - 将文件数据作为 Bzip2 写入 servlet 响应的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2299758/

相关文章:

java - JSF + WatchService + 线程

java - 得到 JdkVersion classNotFoundException

java - 从属性文件加载 JPA 存储库查询

java - Spring MVC 中 content-type application/x-www-form-urlencoded 的请求参数顺序

eclipse - java.lang.NoClassDefFoundError : org/eclipse/wst/web/internal/deployables/IFlatDeployable 错误

java - 用新值填充 JComboBox

java - 仅打印以 pre Java 开头的单词

java - 如何复制图像/缓冲图像

java - "Stream Closed"显然是由多次提交引起的错误

java - 在 tomcat servlet 中检测客户端断开连接?