Domanda

Sto cercando di ottenere Tomcat di scrivere il contenuto servlet come un file bzip2 (requisito sciocco, forse, ma è a quanto pare necessaria per un lavoro di integrazione). Sto utilizzando il framework Spring quindi questo è in un AbstractController.

Sto usando la libreria bzip2 da http://www.kohsuke.org/bzip2/

posso ottenere il contenuto bzippati bene, ma quando il file viene scritto sembra contenere una serie di metadati ed è riconoscibile come un file bzip2.

Ecco quello che sto facendo

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

Questo viene chiamato dalla seguente metodo in primavera abstractcontroller

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

Ho preso un paio di colpi a esso in diversi approcci, tra cui la scrittura direttamente al ServletOutput ma sono abbastanza perplesso e non riesco a trovare nessuna molti esempi / on-line.

Qualche consiglio da chiunque abbia incontrato questo prima sarebbe molto apprezzato. biblioteche Alternative / approcci vanno bene, ma purtroppo deve essere bzip2'd.

È stato utile?

Soluzione

L'approccio postato è davvero strano. Ho riscritto in modo che ha più senso. Fare un tentativo.

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

Si vede, basta avvolgere il flusso di output della risposta con CBZip2OutputStream e scrivere il byte[] ad esso.

Si può capitare di vedere IllegalStateException: Response already committed venire dopo questo nei log dei server (con il download di essere correttamente inviato tra l'altro), allora vuol dire che la primavera sta cercando di inoltrare la richiesta / risposta in seguito. Non faccio primavera, quindi non posso andare in dettaglio, ma si dovrebbe almeno istruire primavera a stare lontano dalla risposta. Non lasciare che faccia una mappatura, in avanti o qualsiasi altra cosa. Penso di tornare null sufficiente.

Altri suggerimenti

Si potrebbe trovare a lavorare con CompressorStreamFactory commons-impacco un po 'più facile. Si tratta di un defunto della versione Ant si sta già lavorando con e finisce per 2 linee differenti dall'esempio di BalusC.

Più o meno una questione di preferenze biblioteca.

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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top