Come produrre un documento binario basato su un documento HTML usando i filtri in Java
-
20-08-2019 - |
Domanda
Questo può essere un po 'confuso ma ho qualche problema. Il mio obiettivo è quello di prendere un documento HTML di input e quindi elaborare quel documento e utilizzare i dati HTML per produrre un documento immagine. Ad esempio, un utente richiederà un URL, con alcune azioni = png nella stringa di query e quindi il filtro verrà invocato per l'URL e il documento di immagine di output.
Ho provato di tutto ma nel mio ambiente (Websphere), sono in grado di produrre solo un tipo. Se il tipo di input è text / html, allora posso solo produrre un documento di testo, non riesco a produrre un documento binario. Perché? Perché ogni volta ricevo un'eccezione di stato illegale.
[29/01/09 17: 59: 57: 576 EST] 00000020 SystemErr R java.lang.IllegalStateException: SRVE0209E: Writer già ottenuto [29/01/09 17: 59: 57: 576 EST] 00000020 SystemErr R all'indirizzo com.ibm.ws.webcontainer.srt.SRTServletResponse.getOutputStream (SRTServletResponse.java:505)
Sto usando lo pseudo codice per non rivelare tutto il mio codice:
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>
com.util.TestFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/index_test2.html</url-pattern>
</filter-mapping>
Il codice della classe Wrapper è essenzialmente questo:
public class ContentCaptureServletResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream contentBuffer;
private PrintWriter writer;
public PrintWriter getWriter() throws IOException {
if (writer == null) {
contentBuffer = new ByteArrayOutputStream();
writer = new PrintWriter(contentBuffer);
}
return writer;
}
public String getContent(){
try {
writer = getWriter();
} catch (IOException e) {
e.printStackTrace();
}
writer.flush();
String xhtmlContent = new String(contentBuffer.toByteArray());
System.out.println(xhtmlContent);
return xhtmlContent;
}
}
E il codice filtro è questo:
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
final String renderType = request.getParameter("R");
final String renderClassName = request.getParameter("C");
if ((renderType != null) && (renderClassName != null)) {
try {
this.setFilterChain(filterChain);
response.setContentType("image/png");
PrintWriter out = response.getWriter();
// I call getWriter but not BOTH!
//response.getOutputStream();
response.getWriter();
// Build up the HTML document into a string.
CaptureResponse capContent = new CaptureResponse(response);
this.mainFilterChain.doFilter(req, );
String myString = capHtmlContent.getContent();
// What I really want to do here is output an output stream
// so I can write a binary image
processStr(myString);
response.getOutputStream();
response.write(binaryimage)
} catch (Exception e) {
e.printStackTrace();
}
// No data will be output to the user.
} else {
filterChain.doFilter(request, response);
} // End of if-else
} // End of the method.
Il codice funziona se voglio prendere un documento di testo HTML di input. Sto assumendo a causa del flusso open printwriter. Ma ho problemi ad andare in un formato diverso. Fondamentalmente, perché non posso chiamare response.getOutputStream ()
Soluzione
Il problema sembra essere che stai aprendo la risposta Writer prima di racchiudere la risposta.
Sembra che dovresti essere in grado di fare:
this.setFilterChain(filterChain);
CaptureContent capContent = new CaptureResponse(response);
doFilter()
process();
response.setContentType("image/png");
response.getOutputStream().write(imagedata);
Non puoi assolutamente aprire in sicurezza sia Writer che OutputStream
Altri suggerimenti
Non ho esperienza con Websphere, ma un problema comune è che provi a manipolare l'intestazione HTTP dopo esserti già impegnato a inviare il corpo: una volta che il server web ha iniziato a consegnare il contenuto, non puoi più aggiornare le intestazioni poiché sono già stati inviati.
Forse è necessario rivedere la documentazione e gli esempi. Ad esempio, non vedo perché chiami response.get * () senza effettivamente guardare il risultato. Sei sicuro che sia necessario o è perché hai tagliato il tuo codice?
Saluti, Volker