I've been trying to load a PDF file located at "/resources/pdf/". I want to load the pdf, fill the form fields and return a stream. This is working so far, there are no errors or exceptions.
The problem is that when the resulting PDF is printed parts of the document is missing. Using this pdf, it is just printing the form fields, but not the images or the text. The code is running in a tomcat7 in combination with primefaces:
public StreamedContent modify() {
String pdfFile = "mypdf.pdf";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
InputStream istream = getClass().getResourceAsStream("/pdf/" + pdfFile);
PdfReader reader = new PdfReader(istream);
pdfStamper = new PdfStamper(reader, bos );
pdfForm = pdfStamper.getAcroFields();
// fillData();
pdfStamper.close();
reader.close();
istream.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
bis.close();
bos.close();
return new DefaultStreamedContent( bis, "application/pdf", "report.pdf" );
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
I do build project this way: mvn clean install tomcat7:redeploy -DskipTests
Any idea what is wrong? Thanks.
I have finally decided to do it in another way.
In the project properties file I have added a new property with the path where the PDF is located, in this way I can load the pdfReader object with File through the new FileInputStream
Final code
public StreamedContent modify() {
File file = getPdfFile();
PdfReader reader = new PdfReader(new FileInputStream(file));
pdfStamper = new PdfStamper(reader, bos );
// fillData();
pdfStamper.close();
bos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
return new DefaultStreamedContent( bis, "application/pdf", "report.pdf" );
}
public File getPdfFile() {
try {
Properties prop = new Properties();
prop.load(getClass().getClassLoader()
.getResourceAsStream("myfile.properties"));
String pdfPath = prop.getProperty("pdf.path");
String pdfName = prop.getProperty("pdf.name");
File file = new File(pdfPath + pdfName);
return file;
} catch (Exception ex) {
LOGGER.error("ERROR: " + ex.getMessage());
return null;
}
}
Thank you very much!
Regards,
Update:
I just experienced the same problem! After intensive research I detected that maven broke the encoding of my PDF files. I should have more carefully read MKLs comment ;-)
I added the resource plugin to my maven project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<nonFilteredFileExtensions>
<!-- Please note that images like jpg, jpeg, gif, bmp and png are (already) implicitly excluded -->
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
Old post:
Your post lacks vital information:
How do you print your report.pdf? From the webbrowser or Adobe Reader? Please post the report.pdf so we can analyze.
What I understand is, that the code you posted works fine (no error, no exception). The problem occurs only at printing?
One shot what might be wrong:
You do not set the encoding (e.g. UTF-8) for your stream:
return new DefaultStreamedContent( bis, "application/pdf", "report.pdf", "YourEncoding");
and by the way the original PDF is buggy, too (E.g. Preflight reports serveral errors.)
Related
As I've become interested in iTextSharp I need to learn C#. Since I know a bit of AutoHotkey (simple yet powerful script programming language for Windows) it is easer for me. However, I often come across code written in Java which is said to be easily converted to C#. Unfortunetly, I have some problems with it. Let's have a look at original code written by Bruno Lowagie.
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfDictionary root = reader.getCatalog();
PdfDictionary names = root.getAsDict(PdfName.NAMES);
names.remove(PdfName.EMBEDDEDFILES);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.close();
}
This is what I have managed to write on my own:
static void removeFiles(string sourceFilePath, string destFilePath)
{
try
{
// read src file
FileStream inputStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.None);
Document source = new Document();
// open for reading
PdfWriter reader = PdfReader.GetInstance(inputStream);
source.Open();
// create dest file
FileStream outputStream = new FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
Document dest = new Document();
PdfWriter writer = PdfWriter.GetInstance(dest, inputStream); // open stream from src
// remove embedded files from dest
PdfDictionary root = dest.getCatalog().getPdfObject();
PdfDictionary names = root.getAsDictionary(PdfName.Names);
names.remove(PdfName.EmbeddedFiles);
// close all
source.Close();
dest.Close();
}
catch (Exception ex)
{
}
}
Unfortunately, there are many errors such as:
'Document' does not contain a definition for 'getCatalog' and no extension method 'getCatalog'
'PdfReader' does not contain a definition for 'GetInstance'
This is what I have managed to do after countless hours of coding and googling.
There are some iTextSharp examples available. See for instance: How to read a PDF Portfolio using iTextSharp
I don't know much about C#, but this is a first attempt to fix your code:
static void RemoveFiles(string sourceFilePath, string destFilePath)
{
// read src file
FileStream inputStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.None);
// open for reading
PdfReader reader = new PdfReader(inputStream);
FileStream outputStream = new FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
PdfStamper stamper = new PdfStamper(reader, outputStream);
// remove embedded files
PdfDictionary root = reader.Catalog;
PdfDictionary names = root.GetAsDict(PdfName.NAMES);
names.Remove(PdfName.EMBEDDEDFILES);
// close all
stamper.Close();
reader.Close();
}
Note that I don't understand why you were using Document and PdfWriter. You should use PdfStamper instead. Also: you are only removing the document-level attachments. If there are file attachment annotations, they will still be present in the PDF.
Does anyone know how image file can be easily converted into PDF format. What I need is to get the image from database and display it on the screen as PDF. What am I doing wrong? I tried to use iText but with no results.
My code:
StreamResource resource = file.downloadFromDatabase();//get file from db
Document converToPdf=new Document();//Create Document Object
PdfWriter.getInstance(convertToPdf, new FileOutputStream(""));//Create PdfWriter for Document to hold physical file
convertToPdf.open();
Image convertJpg=Image.getInstance(resource); //Get the input image to Convert to PDF
convertToPdf.add(convertJpg);//Add image to Document
Embedded pdf = new Embedded("", convertToPdf);//display document
pdf.setMimeType("application/pdf");
pdf.setType(Embedded.TYPE_BROWSER);
pdf.setSizeFull();
Thanks.
You're not using iText correctly:
You never close your writer, so the addition of the image never gets written to the outputstream.
You pass an empty string to your FileOutputStream. If you want to keep the pdf in memory, use a ByteArrayOutputStream. If not, define a temporary name instead.
You pass your Document object, which is a iText-specific object to your Embedded object and treat it like a file. It is not a pdf-file or byte[]. You'll probably want to pass either your ByteArrayOutputStream or read the temp file as a ByteArrayOutputStream into memory and pass that to Embedded.
Maybe someone will use (Vaadin + iText)
Button but = new Button("FV");
StreamResource myResource = getPDFStream();
FileDownloader fileDownloader = new FileDownloader(myResource);
fileDownloader.extend(but);
hboxBottom.addComponent( but );
private StreamResource getPDFStream() {
StreamResource.StreamSource source = new StreamResource.StreamSource() {
public InputStream getStream() {
// step 1
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
// step 2
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
com.itextpdf.text.pdf.PdfWriter.getInstance(document, baos);
// step 3
document.open();
document.add(Chunk.NEWLINE); //Something like in HTML :-)
document.add(new Paragraph("TEST" ));
document.add(Chunk.NEWLINE); //Something like in HTML :-)
document.newPage(); //Opened new page
//document.add(list); //In the new page we are going to add list
document.close();
//file.close();
System.out.println("Pdf created successfully..");
} catch (DocumentException ex) {
Logger.getLogger(WndOrderZwd.class.getName()).log(Level.SEVERE, null, ex);
}
ByteArrayOutputStream stream = baos;
InputStream input = new ByteArrayInputStream(stream.toByteArray());
return input;
}
};
StreamResource resource = new StreamResource ( source, "test.pdf" );
return resource;
}
OnClick of button on JSP Page, I am trying to download more than one pdf one by one using java code but not able to done it and Using Following snippet code for the same
Document document[]= new Document[20];
httpServletResponse.setHeader("Content-Disposition",
"attachment;filename=welcome.pdf");
httpServletResponse.setContentType("application/pdf");
try{
for(int i=0;i<3;i++)
{
System.out.println(i);
document[i]=new Document();
PdfWriter.getInstance(document[i], httpServletResponse.getOutputStream());
document[i].open();
document[i].add(new Paragraph("Hello Prakash"));
document[i].add(new Paragraph(new Date().toString()));
document[i].close();
}
}catch(Exception e){
e.printStackTrace();
}
It is not working and alaways only one .PDF file is downloading, anyone help me out?
One could prepare a page, that does multiple requests to the server, every one which of downloads a PDF. This is not so nice a user experience.
I would use a zip file containing all PDFs:
response.setContentType("application/zip"); // application/octet-stream
response.setHeader("Content-Disposition", "inline; filename=\"all.zip\"");
try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
for (int i = 0; i < 3; i++) {
ZipEntry ze = new ZipEntry("document-" + i + ".pdf");
zos.putNextEntry(ze);
// It would be nice to write the PDF immediately to zos.
// However then you must take care to not close the PDF (and zos),
// but just flush (= write all buffered).
//PdfWriter pw = PdfWriter.getInstance(document[i], zos);
//...
//pw.flush(); // Not closing pw/zos
// Or write the PDF to memory:
ByteArrayOutputStream baos = new ...
PdfWriter pw = PdfWriter.getInstance(document[i], baos);
...
pw.close();
byte[] bytes = baos.toByteArray();
zos.write(baos, 0, baos.length);
zos.closeEntry();
}
}
Just read, you cannot use ZIP download.
Maybe you might use HTML5 offering a nicer download experience (progress bars?).
I'm trying to update a Microsoft Word document using Apache POI. The msword document is a template that contains a number of placeholders in the form "${place.holder}" and all I need to do is to replace the holders with specific values. What I've got so far is
private void start() throws FileNotFoundException, IOException {
POIFSFileSystem fsfilesystem = null;
HWPFDocument hwpfdoc = null;
InputStream resourceAsStream = getClass().getResourceAsStream("/path/to/document/templates/RMA FORM.doc");
try {
fsfilesystem = new POIFSFileSystem(resourceAsStream );
hwpfdoc = new HWPFDocument(fsfilesystem);
Range range = hwpfdoc.getRange();
range.replaceText("${rma.number}","08739");
range.replaceText("${customer.name}", "Roger Swann");
FileOutputStream fos = new FileOutputStream(new File("C:\\temp\\updatedTemplate.doc"));
hwpfdoc.write(fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The program runs without errors. If I look in the output file with a Hex editor I can see that the placeholders have been replaced by the program. However, when I try to open the document with MSWord, MSWord crashes.
Is there a step (series of steps) that I'm missing, or am I basically out of luck with this? Do I need to adjust any counters because the length of the replacement text is not the same as the length of the replaced text?
Regards
use new FileInputStream() instead of getClass().getResourceAsStream("/path/to/document/templates/RMA FORM.doc");
I'm trying to generate an SVG image and then transcode it to PNG using Apache Batik. However, I end up with an empty image and I can't see why.
I use the Document from SVGDomImplementation as the base for my transcoding (to avoid writing the SVG to disk and loading it again). Here's an example:
DOMImplementation domImpl = SVGDOMImplementation.getDOMImplementation();
String namespace = SVGDOMImplementation.SVG_NAMESPACE_URI;
Document document = domImpl.createDocument(namespace, "svg", null);
//stuff that builds SVG (and works)
TranscoderInput transcoderInput = new TranscoderInput(svgGenerator.getDOMFactory());
PNGTranscoder transcoder = new PNGTranscoder();
transcoder.addTranscodingHint(PNGTranscoder.KEY_WIDTH, new Float(svgWidth));
transcoder.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, new Float(svgHeight));
try {
File temp = File.createTempFile(key, ".png");
FileOutputStream outputstream = new FileOutputStream(temp);
TranscoderOutput output = new TranscoderOutput(outputstream);
transcoder.transcode(transcoderInput, output);
outputstream.flush();
outputstream.close();
name = temp.getName();
} catch (IOException ioex) {
ioex.printStackTrace();
} catch (TranscoderException trex) {
trex.printStackTrace();
}
My problem is that the resulting image is empty and I can't see why. Any hints?
I think it depends on how you're creating the SVG document. What are you using svgGenerator for (which I assume is an SVGGraphics2D)?
TranscoderInput transcoderInput = new TranscoderInput(svgGenerator.getDOMFactory());
If you've built up the SVG document in document, then you should pass it to the TranscoderInput constructor.
This page has an example of rasterizing an SVG DOM to a JPEG.