1

Tomcatにサーブレットの内容を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+";)");

これは、Springabstractcontrollerの次のメソッドから呼び出されています

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

ServletOutputに直接書き込むなど、さまざまなアプローチでいくつかの試みを行いましたが、かなり困惑しており、オンラインで例を見つけることができません。

これまでにこれに出くわしたことがある人からのアドバイスをいただければ幸いです。代替のライブラリ/アプローチは問題ありませんが、残念ながらbzip2化する必要があります。

4

2 に答える 2

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 が後でリクエスト/レスポンスを転送しようとしていることを意味します。私はSpringをやっていないので詳しくは言えませんが、せめてSpringにはレスポンスを控えるように指示したほうがいいです。転送などのマッピングを行わせないでください。null 返品で十分だと思います。

于 2010-02-20T03:22:44.950 に答える
2

commons-compressからCompressorStreamFactoryを使用する方が少し簡単であることに気付くかもしれません。これは、既に使用している 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();
}
于 2010-02-20T06:13:59.313 に答える