Question

Je suis en train d'obtenir Tomcat pour écrire le contenu de servlet en tant que fichier bzip2 (exigence peut-être idiot, mais il est apparemment nécessaire pour un travail d'intégration). J'utilise le framework Spring est donc ce dans un AbstractController.

J'utilise la bibliothèque bzip2 de http://www.kohsuke.org/bzip2/

Je peux obtenir le contenu BZippée bien, mais lorsque le fichier est écrit il semble contenir un tas de méta-données et est méconnaissable en tant que fichier bzip2.

Voici ce que je fais

// 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+";)");

est appelée à partir de la méthode suivante au printemps AbstractController

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

J'ai pris quelques coups à dans différentes approches, y compris l'écriture directement à la ServletOutput mais je suis assez perplexe et ne trouve pas beaucoup d'exemples / en ligne.

Tous les conseils de quelqu'un qui est venu dans ce avant serait très apprécié. bibliothèques / des approches alternatives sont très bien, mais malheureusement, il doit être bzip2.

Était-ce utile?

La solution

L'approche affichée est en effet bizarre. Je l'ai réécrit pour qu'il est plus logique. Lui donner un essai.

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

Vous voyez, juste envelopper le flux de sortie de la réponse avec CBZip2OutputStream et écrire le byte[] lui.

Vous pouvez arriver à voir IllegalStateException: Response already committed venir après dans les journaux de serveur (avec le téléchargement étant correctement envoyé par la voie), cela signifie que le printemps tente de transmettre la demande / réponse par la suite. Je ne fais pas du printemps, donc je ne peux pas aller en détail, mais vous devriez au moins demander Spring rester à l'écart de la réponse. Ne le laissez pas faire une correspondance, vers l'avant ou peu importe. Je pense que le retour null suffit.

Autres conseils

Vous trouverez peut-être travailler avec CompressorStreamFactory de commons-compress un peu plus facile. Il est une personne décédée de la version Ant vous travaillez déjà avec et finit par 2 lignes différentes de l'exemple de BalusC.

Plus ou moins une question de préférence bibliothèque.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top