a4j:mediaOutput not rendering PDF - jsf

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.

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.

Related

How to display pdf on JSF

Hi my code is as follows:
public StreamedContent getTempPdfFile() throws IOException {
File testPdfFile = new File("D:\\AFC150_20180819_0103.pdf");
streamedContent = new DefaultStreamedContent(new FileInputStream(testPdfFile), "application/pdf",
"AFC150_20180819_0103.pdf");
return streamedContent;
}
<h:panelGrid columns="1" cellpadding="5">
<p:media value="#{realReport.tempPdfFile}" player="pdf" width="1000px" height="300px">
<f:param name="id" />
</p:media>
</h:panelGrid>
But the PDF file is not getting displayed on the page.
Here is my sample, hope it helps, the code has the inline and attachment:
void sendBackPDFToClient()
{
//File temp = File.createTempFile(fileName, ".pdf");
File testPdfFile = new File("D:\AFC150_20180819_0103.pdf");
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType("application/pdf");
ec.setResponseContentLength((int)testPdfFile.length());
//Inline
//ec.setResponseHeader("Content-Disposition", "inline; filename=\"" + testPdfFile.getName() + "\"");
//Attach for Browser
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + testPdfFile.getName() + "\"");
OutputStream output = ec.getResponseOutputStream();
Files.copy(testPdfFile.toPath(), output);
fc.responseComplete();
}
Have you tried the Document Viewer component of PrimeFaces Extensions?
I think its much easier to use than p:media and offers more features including ability to load it from a URL, a Stream, or a Resource. That basic example shows you how to do it with all 3 types.
JAVA:
public StreamedContent getTempPdfFile() throws IOException {
File testPdfFile = Paths.get("D:\\AFC150_20180819_0103.pdf").toFile();
return new DefaultStreamedContent(new FileInputStream(testPdfFile), "application/pdf",
"AFC150_20180819_0103");
}
XHTML:
<pe:documentViewer height="500" width="1000" value="#{realReport.tempPdfFile}"/>

the web camera in primefaces is not increse either the width or the heigh of the camera in primefaces code blow

in primefaces web camera is not increase the size of the photo or the camera in JSF code how to solve this proble
<p:photoCam widgetVar="pc" listener="#{photoCamView.oncapture}" update="photo" />
<p:commandButton type="button" value="Capture" onclick="PF('pc').capture()"/>
<p:outputPanel id="photo">
<p:graphicImage name="#{photoCamView.filename}" rendered="#{not empty photoCamView.filename}"/>
</p:outputPanel>
</h:form>
<br />
and the Java code is
public void oncapture(CaptureEvent captureEvent) {
filename = getRandomImageName();
byte[] data = captureEvent.getData();
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
System.out.println("HH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11");
File newFileName = new File("C:\\Users\\adane\\Desktop\\PhotoCam\\Image"+filename + ".jpeg");
FileImageOutputStream imageOutput;
try {
imageOutput = new FileImageOutputStream(newFileName);
imageOutput.write(data, 0, data.length);
imageOutput.close();
}
catch(IOException e) {
throw new FacesException("Error in writing captured image.", e);
}
}

p:upload file doesn't work with pdf extension neither of the rest of extension like png,docx,jpeg,gif?

and I cant' store file more than 10Mb
the primary problrm is why doesn't except pdf file???
this is my ManagedBean
file upload function :-
public void fileUploadListener(FileUploadEvent e) throws IOException, Exception {
this.file = e.getFile();
File oStream = new File("c:\\test.pdf");
courseResourceBean.update(item);
oStream.createNewFile();
Long sss = file.getSize();
InputStream inputStream = file.getInputstream();
FileOutputStream outputStream = new FileOutputStream(oStream);
byte[] buffer = new byte[sss.byteValue()];
int lenght;
while ((lenght = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, lenght);
}
outputStream.close();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("File Uploaded Successfully" + file.getSize()));
String extension = file.getContentType();
}
file download function :-
public void prepDownload(Long id) throws Exception {
File files = new File("c:\\test.pdf");
InputStream input = new FileInputStream(files);
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
setDownload(new DefaultStreamedContent(input, externalContext.getMimeType(files.getName()), files.getName()));
System.out.println("PREP = " + download.getName());
}
and this is the xhtml page
upload :-
<p:outputLabel value="#{msg.courseName}, #{msg.inArabic}" style="text-align: right"/>
<p:fileUpload value="#{courseResourceMB.file}" mode="advanced" sizeLimit="200000000000"
fileUploadListener="#{courseResourceMB.fileUploadListener}" update="msg11" >
</p:fileUpload>
downlad:-
<p:commandButton id="downloadLink" value="Download" actionListener="#{courseResourceMB.prepDownload(item.id)}" ajax="false">
<p:fileDownload value="#{courseResourceMB.download}" />
</p:commandButton>

How to show two pdf in differents tabs from java

Sorry for my poor english but I really want to show two pdf reports from jasper report at the same time in differents tabs on browser. I´m working with java jsf, primefaces. The principal idea is when the button is clicked show this reports in diferents tabs. I try to do this:
I have this in the Managed Bean:
public void showReports() {
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep2').click();");
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep3').click();");
}
public void printReport(String name) {
try {
Map<String, Object> mapParametros = new HashMap<>();
mapParametros.put("CORR", corr);
printJasper(mapParametros, new File("/Jasper/Reports/" + name));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void printJasper(Map<String, Object> reportValues, File fileJ) {
ByteArrayInputStream input = null;
BufferedOutputStream output = null;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
try {
facesContext = FacesContext.getCurrentInstance();
externalContext = facesContext.getExternalContext();
response = (HttpServletResponse) externalContext.getResponse();
FileInputStream file = new FileInputStream(fileJ);
JasperReport compiledTemplate = (JasperReport) JRLoader.loadObject(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
JasperPrint jasperPrint = JasperFillManager.fillReport(compiledTemplate, reportValues, dataSourceP.getConnection());
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print();");
exporter.exportReport();
input = new ByteArrayInputStream(out.toByteArray());
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(out.toByteArray().length));
response.setHeader("Content-Disposition", "inline; filename=\"ticket.pdf\"");
output = new BufferedOutputStream(response.getOutputStream(), Constants.DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} catch (Exception exception) {
System.out.println(exception.getMessage());
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (Exception exception) {
/* ... */
}
}
facesContext.responseComplete();
}
An this in my view:
<h:form>
<p:commandButton value="Show them" action="#{reportBean.showReports()}"/>
<p:commandButton value="REPORT 1" id="rep1" style="font-size: 25px; float:right;visibility: hidden;" action="#{reportBean.printReport("Report1")}" ajax="false" onclick="this.form.target = '_blank';"/>
<p:commandButton value="REPORT 2" id="rep2" style="font-size: 25px; float:right;visibility: hidden;" action="#{reportBean.printReport("Report2")}" ajax="false" onclick="this.form.target = '_blank';"/>
</h:form>
But doesn´t work, it just show the second report.
Help!.
Thanks!
Try a hit using p:commandLink like i am using.
<p:commandLink id="PreviewR1" value="Print Preview" ajax="false" action="#{reportBean.printReport("Report1")}" target="_blank" />
<p:commandLink id="PreviewR2" value="Print Preview" ajax="false" action="#{reportBean.printReport("Report2")}" target="_blank" />
It will open the report 1 & 2 in separate browser tab while your original web page will remains the same.
You just don't click the correct buttons:
public void showReports() {
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep2').click();");
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep3').click();");
}
You're clicking on rep2 and rep3. rep3 doesn't exists, you need to click on rep1 instead. That should be the reason why only the 2nd report is shown.
Finally I found other way to solve it.
The method showReports() instead to click two buttons, this open two xhtml that each one has inside of <h.form> a remotecommand with autorun true, that show the reports. I don´t know if it´s the best way to do it, but It works.
Thanks for all your comments

JSF PrimeFaces FileDownload problem

I'm using PrimeFaces for a new project and it's quite an impressive set of components.
Anyway, I have problem with "real world" use of filedownload component.
In my page I have a datalist that shows the attachments related to a particular document, and I want provide a link to directly download that file inside the datalist item.
Here's my xhtml code:
<p:dataList id="ListaAllegati" value="#{documentBean.documento.allegati}" type="definition" var="attach" style="border: none" ">
<f:facet name="description">
<h:outputText value="#{attach.name}" />
<p:commandLink ajax="false" title="Download" action="#{documentBean.selectAttach}>
<h:graphicImage style="margin-left: 10px; border: none" value="./images/article.png" height="24" width="24" ></h:graphicImage>
<p:fileDownload value="#{documentBean.downloadFile}"/>
<f:setPropertyActionListener target="#{documentBean.selectedAttach}" value="#{attach}" />
</p:commandLink>
</f:facet>
</p:dataList>
and the relative java bean (request scoped):
private StreamedContent downloadFile;
public StreamedContent getDownloadFile() {
log.info("getter dell'allegato invocato");
InputStream stream = null;
byte[] rawFile = null;
if (selectedAttach == null) {
log.warn("Nessun allegato passato");
return null;
} else {
try {
log.info("Recupero del file " + selectedAttach.getGuid());
rawFile = attachManager.retrieveFile(selectedAttach.getGuid());
} catch (Exception e) {
String msg = "Errore durante il recupero del file";
log.error(msg, e);
FacesMessage fmsg = new FacesMessage(msg, "");
FacesContext.getCurrentInstance().addMessage(null, fmsg);
}
stream = new ByteArrayInputStream(rawFile);
DefaultStreamedContent file = new DefaultStreamedContent(stream,
selectedAttach.getMimeType(), selectedAttach.getName());
return file;
}
}
public void selectAttach() {
log.info("commandLink action invocata");
}
private Allegato selectedAttach;
public Allegato getSelectedAttach() {
return selectedAttach;
}
public void setSelectedAttach(Allegato selectedAttach) {
log.info("Allegato selezionato");
if (selectedAttach==null) log.warn("L'allegato passato è nullo");
this.selectedAttach = selectedAttach;
}
So, couple of question:
Am I doing the right thing trying to pass the selected attachment that way? Otherwise, how can I pass a parameter to tell the bean wich attachment has been clicked?
Why the first time I click the command link, nothing happen? It make a roundtrip with server, but nothing happens. Second time, it gives me an exception.
Why documentBean.selectAttach is never called and the documentBean.selectedAttach property is never set (neither the second time)?
Thanks to anyone for any hint
How to get the row object from the datatable is answered in this question:
How can I pass selected row to commandLink inside dataTable?
This answers basically all the three questions.
As to the exception in the second click, that's likely because you didn't return from the catch block when an exception is been thrown in your getDownloadFile() method. You're continuing the remnant of the code flow while the rawFile is still null. Fix it accordingly as well. Add a return null to the end of catch or something. Better yet, you should be posting the entire stacktrace in the question as you don't seem to be able to understand it. It basically already contains the answer :)
Primefaces has its own dedicated servlet for file download and upload components that handle all of this asynchronously.
Try doing something like what I have in my code
<p:commandLink ajax="false" actionListener="#{managedBean.downloadAction(object)}">
<span class="ui-icon icoFolderGo" style="padding-right: 1.5em;" />
<p:fileDownload value="#{managedBean.downloadContentProperty}" />
</p:commandLink>
And in the managed bean,
public void downloadAction(Object object) {
try {
InputStream stream = // get input stream from argument
this.setDownloadContentProperty(new DefaultStreamedContent(stream, "application/pdf", "filename.pdf");
} catch (Exception e) {
log.error(e);
}
}
public void setDownloadContentProperty(StreamedContent downloadContentProperty) {
this.downloadContentProperty = downloadContentProperty;
}
public StreamedContent getDownloadContentProperty() {
return downloadContentProperty;
}

Resources