Primefaces InputStream generating corrupted PDF in fileDownload - java

I need your help in solving the issue of generating a corrupted PDF file from an InputStream which is used in the fileDownload Component. I am having a PDF that is generated using the iText and then I am converting it to an inputStream, so I can use it as an input in the fileDownload component. After clicking on the download commandButton, I will download the file and open it, it will show a message:
The Adobe Reader can not open the file "sample.pdf" because it is
either not supported file type or it is damaged
The bean code is:
private StreamedContent file;
public void createPdf() {
try {
Document doc = Document(PageSize.A4, 50, 50, 50, 50);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in ;
PdfWriter writer;
writer = PdfWriter.getInstance(doc, out);
doc.open();
doc.add(new Paragraph("Hello World!"));
in = new ByteArrayInputStream(out.toByteArray());
file = new DefaultStreamedContent(in, "application/pdf", "sample.pdf");
} catch (Exception e) {
e.printStackTrace();
}
}
And the jsf code is:
<p:commandButton value="Download" ajax="false"
onclick="PrimeFaces.monitorDownload(start, stop);"
icon="ui-icon-arrowthick-1-s" actionListener="#{pdf.createPdf}">
<p:fileDownload value="#{pdf.file}"/>
</p:commandButton>
So how to fix the issue

Shouldn't there be doc.close() before you start coping bytes from out? Is the file also corrupted if you save it to hard drive instead of sending it to browser?

Related

Java code and iText PDF library will not display shipping label image in browser

I have a Java method that when called, displays a shipping label pdf image in my browser. I'm using iText, as well as Apache Commons libraries for this.
import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64;
import com.itextpdf.text.*;
...
public void constructLabel(HttpServletResponse response) {
Document document = new Document();
byte[] image = null;
Image labelImage = null;
try {
document.setPageSize(PageSize.LETTER);
PdfWriter.getInstance(document, response.getOutputStream());
document.open();
String base64Label = "a3B4GHHh6Y0m923xKj="; //<--This is longer, but I shortened it for this question
image = Base64.decodeBase64(base64Label.getBytes());
labelImage = Image.getInstance(image);
labelImage.setAlignment(Image.TOP);
labelImage.scalePercent(new Float("35"));
document.add(labelImage);
response.getOutputStream().write(image);
response.setContentType("application/pdf");
response.setContentLength(image.length);
document.close();
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
}
...
For UPS labels, it works fine. When my code runs a base-64 encoded UPS label, the label displays in the browser. But for FedEx labels, I get an error modal in the browser that says "Error Failed to load PDF document." Please see pictures of the labels (printed from an online PDF converter) and error modal below.
This has me left in the dark in that there are no errors or exceptions or stack traces in the console at all.
How can I get this code to show a PDF image of the FedEx label in the browser?

Page's HTML code written into file when file is downloaded from web app

I have a downloadfile servlet code that will dynamically add contents into a CSV file for users to download. However instead of having the contents I want added into the CSV file, the page's HTML code appears in the file instead. Can anyone tell me what is causing this bug? Here's my controller code
response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment";
filename="\\evaluations.csv\\");
try
{
OutputStream outputStream = response.getOutputStream();
String outputResult = "xxxx, yyyy, zzzz, aaaa, bbbb, ccccc, dddd, eeee, ffff, gggg\n";
outputStream.write(outputResult.getBytes());
outputStream.flush();
outputStream.close();
} catch(Exception e) {
status = "Error exporting file, please try again later";
System.out.println(e.toString());
}
//request.setAttribute("status",status);
//dispatcher = request.getRequestDispatcher("/viewEvaluations.jsp");
//dispatcher.forward(request, response);
EDIT:
Removing the forward request actually stop the HTML code from being copied into the file and I also realized its redundant and I've commented them out. This was the code that was causing the problem.
Well if you just want to reload the current page then you can do a trick:
Your <a> tag should be like this:
Click Here
In Jquery:
$('#test').click(function()
{
location.href='download'; //your download request mapping
setTimeout(function(){location.reload()},2000); //this will reload the current page after 2 seconds.
});
Your controller code will be:
#RequestMapping(value = "download", method = RequestMethod.GET)
public void download(Locale locale, Model model,HttpServletRequest request,HttpServletResponse response,HttpSession session) {
response.setContentType("text/csv");
response.setHeader("Content-disposition", "attachment; filename=evaluations.csv");
try
{
OutputStream outputStream = response.getOutputStream();
String outputResult = "xxxx, yyyy, zzzz, aaaa, bbbb, ccccc, dddd, eeee, ffff, gggg\n";
outputStream.write(outputResult.getBytes());
outputStream.flush();
outputStream.close();
} catch(Exception e) {
//logging
}
}
If you want to make visible an div which is hidden on page load then rather than calling location.reload() u should call $('#divId').show()

Download to folder/files android apps

my problem is that I use in my practice are pdf files. I did not add them into my application. I want pdf files from ftp or a URL to download it. I have no idea about the solution. I've tried a lot ftp code and URL code. All I want, when you pressed the button of the sdcard files from a URL or FTP address to get a download. Thanks for your help.
this code is working for me
public void onClick(View v) {
PrintAttributes printAttrs = new PrintAttributes.Builder().
setColorMode(PrintAttributes.COLOR_MODE_COLOR).
setMediaSize(PrintAttributes.MediaSize.NA_LETTER).
setResolution(new PrintAttributes.Resolution("zooey", PRINT_SERVICE, 300, 300)).
setMinMargins(PrintAttributes.Margins.NO_MARGINS).
build();
PdfDocument document = new PrintedPdfDocument(DynamicPDFHelloWorld.this, printAttrs);
// crate a page description
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(300, 300, 1).create();
// create a new page from the PageInfo
PdfDocument.Page page = document.startPage(pageInfo);
// repaint the user's text into the page
View content = findViewById(R.id.textarea);
content.draw(page.getCanvas());
content.draw(edt.getText().toString().);
// do final processing of the page
document.finishPage(page);
// Here you could add more pages in a longer doc app, but you'd have
// to handle page-breaking yourself in e.g., write your own word processor...
// Now write the PDF document to a file; it actually needs to be a file
// since the Share mechanism can't accept a byte[]. though it can
// accept a String/CharSequence. Meh.
try {
File f = new File(Environment.getExternalStorageDirectory().getPath() + "/pruebaAppModerator.pdf");
FileOutputStream fos = new FileOutputStream(f);
document.writeTo(fos);
document.close();
fos.close();
} catch (IOException e) {
throw new RuntimeException("Error generating file", e);
}
}
});

Rendering generated png into JSF

I built an image form PDF doc inside a JSF backing bean, i need to show image inside JSF page. I found that primefaces has a component named , I defined a variable:
private StreamedContent pdfImage;
according to this example http://www.primefaces.org/showcase/ui/dynamicImage.jsf. In my code
i built pdf using some data and apache PDFBox and save document into:
private byte[] bytesPdf;
My jsf line is
<p:graphicImage value="#{myBean.pdfImage}" rendered="#{myBean.showImage}"/>
After that i call following method that tranform first PDF document page to PNG i get:
public void buildPDFImage() throws IOException{
ByteArrayOutputStream os = new ByteArrayOutputStream();
//Build bufferedImage from pdf bytearray
InputStream input = new ByteArrayInputStream(bytesPdf);
PDDocument archivo=new PDDocument();
archivo=PDDocument.load(input);
PDPage firstPage = (PDPage) archivo.getDocumentCatalog().getAllPages().get(0);
BufferedImage bufferedImage = firstPage.convertToImage();
//File exit=new File("d:/exit.png"); if i do something like this and pass file as param to iowrite image is generated on file system
try {
ImageIO.write(bufferedImage, "png", os);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pdfImage = new DefaultStreamedContent(new ByteArrayInputStream(os.toByteArray()), "image/png");
}
When i run my app after generate pdf image i get this trace
GRAVE: Error Rendering View[/pages/apphuella.xhtml]
java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:2880)
at org.apache.catalina.connector.Request.getSession(Request.java:2577)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:920)
at com.sun.faces.context.SessionMap.getSession(SessionMap.java:235)
at com.sun.faces.context.SessionMap.put(SessionMap.java:126)
at com.sun.faces.context.SessionMap.put(SessionMap.java:61)
at org.primefaces.component.graphicimage.GraphicImageRenderer.getImageSrc(GraphicImageRenderer.java:105)
at org.primefaces.component.graphicimage.GraphicImageRenderer.encodeEnd(GraphicImageRenderer.java:45)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1763)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1756)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
at
I would know if i´m using correctly if don´t how could i use it to show generated png(and other images)?, also if there´s other option to show runtime generated images on JSF pages.
Thanks in advance
At first, you need to keep the file a temporary directory. After that you should render the file again.
Try as below
Backing Bean
private String filePath;
public String filePath() {
return filePath;
}
private String getSystemPath() {
Object context = getFacesContext().getExternalContext().getContext();
String systemPath = ((ServletContext)context).getRealPath("/");
return systemPath;
}
public void buildPDFImage() throws IOException {
// create any kind of file types.
byte[] cotent = --> take byte array content of your files.
Stirng fileName = "xxx.pdf" or "xxx.png" --> your file name
String dirPath = "/pdf/" or "/images/"; --> a directory to place created files.
filePath = dirPath + fileName
createFile(new File(getSystemPath() + filePath), content);
}
private void createFile(File file, byte[] content) {
try {
/*At First : Create directory of target file*/
String filePath = file.getPath();
int lastIndex = filePath.lastIndexOf("\\") + 1;
FileUtils.forceMkdir(new File(filePath.substring(0, lastIndex)));
/*Create target file*/
FileOutputStream outputStream = new FileOutputStream(file);
IOUtils.write(content, outputStream);
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Pages
<h:form enctype="multipart/form-data">
<h:commandButton value="Create"/>
<!-- Your Files is image -->
<p:graphicImage value="#{myBean.filePath}"/>
<!--
Your Files is pdf. You need PDF Viewer plugin for your browser.
My FireFox vesion is 20.0. It have default PDF Viewer.
If PDF File cannot display on your browser, it is depond on browser setting also.
-->
<p:media value="#{myBean.filePath}" width="100%" height="300px"/>
</h:form>

Custom font is not working with itextrenderer in java

I have embedded my custom fonts in html with #font-face. This working with all browser but when I am trying to convert it to pdf through itextrender in java custom font is not working anymore its taking default fonts like Arial.
css code:
#font-face {
font-family: Subaru-Medium;
src: url('fonts/Subaru-Medium.eot'); /* IE9 Compat Modes */
src: url('fonts/Subaru-Medium.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('fonts/Subaru-Medium.ttf') format('truetype'), /* Safari, Android, iOS */
url('fonts/Subaru-Medium.svg#svgFontName') format('svg'); /* Legacy iOS */
}
java code:
public static void writePDF(String HTMLfileName, String PDFFileName, String WhereToSave,String fontDirectory)
{
try
{
String url = new File(HTMLfileName).toURI().toURL().toString();
String outputFile = WhereToSave+PDFFileName;
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontResolver=renderer.getFontResolver();
fontResolver.addFont("C:\\Users\\benay.debnath\\Desktop\\htmltemplate\\fonts\\Subaru-Medium.ttf", true);
// fontResolver.addFontDirectory(fontDirectory, true);
SharedContext scontext=renderer.getSharedContext();
// scontext.setDPI(72);
scontext.setDotsPerPixel(12);
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
System.out.println("status:$:true^#^message:$:PDF Genarated^#^fileName:$:"+outputFile);
}catch (Exception e) {
System.out.println("status:$:false^#^message:$:"+e.getMessage());
}
}
Any one can help me to find what I am doing wrong? help much appreciated.
First of all make sure that below font has been installed in your system if not then install font and add following line in your code.
public static void writePDF(String HTMLfileName, String PDFFileName, String WhereToSave,String fontDirectory)
{
try
{
String url = new File(HTMLfileName).toURI().toURL().toString();
String outputFile = WhereToSave+PDFFileName;
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.getFontResolver().addFont("C:\\Windows\\Fonts\\Calibri.ttf","UTF-8",BaseFont.NOT_EMBEDDED);
// fontResolver.addFontDirectory(fontDirectory, true);
SharedContext scontext=renderer.getSharedContext();
// scontext.setDPI(72);
scontext.setDotsPerPixel(12);
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
System.out.println("status:$:true^#^message:$:PDF Genarated^#^fileName:$:"+outputFile);
}catch (Exception e) {
System.out.println("status:$:false^#^message:$:"+e.getMessage());
}
I was also facing same problem i have resolved using above solution. hope this will be useful for you :)
This issue has resolved, the problem was in css I mentioned font-family:"Subaru-Medium" in font file(.ttf) font name was "Subaru Medium" so it was not working. Now its working fine :)

Categories