问题
I have a task of displaying a PDF fetched from the database as a pop up in my JSF application upon clicking a link. However my modal panel isn't rendering the PDF. Instead I get a small dark grey box at the top left corner of the panel.
Here's my XHTML code:
<rich:column styleClass="viewUserTable">
<f:facet name="header">
<h:outputText value="Pdf" />
</f:facet>
<h:outputLink value="#" id="link" style="color:blue;margin: 0 auto;">
Proof
<rich:componentControl for="panel" attachTo="link"
operation="show" event="onclick" />
</h:outputLink>
<rich:modalPanel id="panel" width="350" height="100">
<f:facet name="header">
<h:outputText value="PDF"></h:outputText>
</f:facet>
<a4j:mediaOutput element="object" mimeType="application/pdf"
id="media" session="false" createContent="#{getMyBean.showPdf}"
value="1" style="width:800px; height:600px;" cacheable="false"
standby="loading...">
</a4j:mediaOutput>
</rich:modalPanel>
Here's the method I'm calling in my bean to create content for <a4j:mediaOutput>
.
public void showPdf(OutputStream stream, Object object) throws SQLException, IOException {
Blob proof= myObject.getPdf(someValue);//DB call to get the pdf
InputStream inStream = proof.getBinaryStream();
int length = -1;
byte[] buffer = new byte[4096];
while ((length = inStream.read(buffer)) != -1) {
stream.write(buffer, 0, length);
}
}
I am not sure of the significance of the value
attribute in the <a4j:mediaOutput>
but I found an example on internet where similar content was being fetched from DB and and the value was set as 1. I m using RichFaces 3.3.
回答1:
A friend of mine came to me with this problem today and like you I've struggled to come up with a solution. After some time studying servlet I could solve the problem.
Your method should look like:
public void showPdf(OutputStream stream, Object object) throws SQLException, IOException {
Blob proof = myObject.getPdf(someValue);//DB call to get the pdf
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
ServletOutputStream sout = null;
response.setContentType("application/pdf");
//set a constant for a name to avoid cache and duplicate files on server
response.setHeader("Content-Disposition","filename=fileName_" + (new Date()).getTime() + ".pdf" );
response.setHeader("Content-Transfer-Encoding", "binary;");
response.setHeader("Pragma", " ");
response.setHeader("Cache-Control", " ");
response.setHeader("Pragma", "no-cache;");
response.setDateHeader("Expires", new java.util.Date().getTime());
//Here you will have to pass to total lengh of bytes
//as I used a file I called length method
response.setContentLength(Long.valueOf( proof.someByteLengthProperty() ).intValue());
sout = response.getOutputStream();
byte[] buf = new byte[4096];
InputStream is = new FileInputStream(proof.getBinaryStream());
int c = 0;
while ((c = is.read(buf, 0, buf.length)) > 0) {
sout.write(buf, 0, c);
}
sout.flush();
is.close();
}
It seems that only writing out the OutputStream
is not enough so you have to create a ServletOutputStream
and send it throghout the 'FacesContext' so it can render the output as if it was sending a download stream.
来源:https://stackoverflow.com/questions/27688304/a4jmediaoutput-not-rendering-pdf