PDF Box Creates ZeroByte PDF - java

I am trying to convert a unicode Text File to PDF using PDF box.
Task:
My method takes a unicode encoded TextFile as input and output a PDF file.
Problem:
The PDFs that are created have zero bytes. It is not writing anything.
I am using
Apache PDFBox 2.0.6
This is my code:
public class TexttoPDF {
public File texttoPDF(File textFile) throws Exception {
PDDocument document = new PDDocument();
PDPage blankPage = new PDPage();
PDFont font = PDType1Font.TIMES_ROMAN;
PDPageContentStream contentStream = new PDPageContentStream(document, blankPage);
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(textFile), "UTF8"));
String str;
contentStream.beginText();
contentStream.setFont( font, 12 );
contentStream.moveTextPositionByAmount( 100, 700 );
while ((str = in.readLine()) != null) {
contentStream.drawString(str);
}
contentStream.endText();
document.save( pdffile.getName());
contentStream.close();
document.close();
in.close();
return pdffile;
}
}
How this can be fixed ?

Close your content stream before saving, not after saving. So change
document.save( pdffile.getName());
contentStream.close();
to
contentStream.close();
document.save( pdffile.getName());
(This is described in the FAQ)
Also add the page to your document after calling new PDPage():
document.addPage(blankPage);

Related

No glyph for U+000A in font NotoSerifDevanagari-Bold

i am trying to create pdf using pdfbox. i am storing EditText data as html in Sqlite DB.
now i am retrieving data from sqliteDB and creating pdf of that. this data is having marathi language as well as english language.
i am using NotoSerifDevanagari-Bold font and have added it to assets folder. from there i am accessing this font into code. but i am getting error. please find my code and error below.
AssetManager assetManager;
PDFBoxResourceLoader.init(getApplicationContext());
File FilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
assetManager = getAssets();
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
PDFont font = PDType0Font.load(document, assetManager.open("notoserifdevanagaribold.ttf"));
PDPageContentStream contentStream;
// Define a content stream for adding to the PDF
contentStream = new PDPageContentStream(document, page);
Cursor data = mDatabaseHelper.getDataByDeckname(deckname);
StringBuilder builder=new StringBuilder();
while (data.moveToNext()) {
String front_page_desc = data.getString(3);
String back_page_desc = data.getString(4);
contentStream.beginText();
contentStream.setNonStrokingColor(15, 38, 192);
contentStream.setFont(font, 12);
contentStream.newLineAtOffset(100, 700);
contentStream.showText(Html.fromHtml(front_page_desc).toString());
contentStream.endText();
contentStream.beginText();
contentStream.setNonStrokingColor(15, 38, 192);
contentStream.setFont(font, 12);
contentStream.newLineAtOffset(100, 700);
contentStream.showText(Html.fromHtml(back_page_desc).toString());
contentStream.endText();
}
contentStream.close();
String path = FilePath.getAbsolutePath() + "/temp.pdf";
document.save(path);
document.close();
ERROR
W/System.err: java.lang.IllegalArgumentException: No glyph for U+000A in font NotoSerifDevanagari-Bold
I tried so many examples for above error but i am not able to fix the issue. this error i am getting on contentStream.showText(Html.fromHtml(front_page_desc).toString()); line. can someone please help me on above.
As per this link U+000A is the Unicode for new line. Any font will fail if you try to render it.
In order to avoid such error you can try something like this:
String[] lines = text.split("\\n");
for (String line : lines) {
if (!line.isBlank()) {
contentStream.showText(line);
// add new line here if you want to
}
}

SVG to PNG with Apache Batik then attach to PDF with PDFBox without saving images

So as the title says I am looking for a way to turn SVG to PNG with Apache Batik and then attach this image to PDF file using PDFBox without actually creating the svg and png anywhere.
Currently I have a web form that has SVG image with selectable parts of it.
When the form is submitted I take the "html" part of the svg meaning I keep something like <svg bla bla> <path bla bla/></svg> in a string that Spring then uses to create a ".svg" file in a given folder, then Batik creates a PNG file in the same folder and then PDFBox attaches it to the PDF - this works fine(code below).
//Get the svg data from the Form and Create the svg file
String svg = formData.getSvg();
File svgFile = new File("image.svg");
BufferedWriter writer = new BufferedWriter(new FileWriter(svgFile));
writer.write(svg);
writer.close();
// Send to Batik to turn to PNG
PNGTranscoder pngTranscode = new PNGTranscoder();
File svgFile = new File("image.svg");
InputStream in = new FileInputStream(svgFile);
TranscoderInput tIn = new TranscoderInput(in);
OutputStream os = new FileOutputStream("image.png");
TranscoderOutput tOut = new TranscoderOutput(os)
pngTranscode .transcode(tIn , tOut);
os.flush();
os.close();
//Send to PDFBox to attach to pdf
File pngfile = new File("image.png");
String path = pngfile.getAbsolutePath();
PDImageXObject pdImage = PDImageXObject.createFromFile(path, pdf);
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(1));
contents.drawImage(pdImage, 0, pdf.getPage(1).getMediaBox().getHeight() - pdImage.getHeight());
contents.close();
As you can see there are a lot of files and stuff (need to tidy it up a bit), but is it possible to do this on the run without the creation and constant fetching of the svg and png files?
Given the suggestion in the comments I opted for using ByteArrayOutputStream, ByteArrayInputStream, BufferedImage and LosslessFactory. Its a bit slower than the saving (if you go through it in debug as seems the BufferedImage goes on a holiday first before creating the image).
The sources I found to use are: How to convert SVG into PNG on-the-fly and Print byte[] to pdf using pdfbox
byte[] streamBytes = IOUtils.toByteArray(new ByteArrayInputStream(formData.getSvg().getBytes()));
PNGTranscoder pngTranscoder = new PNGTranscoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pngTranscoder.transcode(new TranscoderInput(new ByteArrayInputStream(streamBytes)), new TranscoderOutput(os));
InputStream is = new ByteArrayInputStream(os.toByteArray());
BufferedImage bim = ImageIO.read(is);
PDImageXObject pdImage = LosslessFactory.createFromImage(pdf, bim);
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(1));
contents.drawImage(pdImage, 0, pdf.getPage(1).getMediaBox().getHeight() - pdImage.getHeight());
contents.close();
Based on the comments and links provided by D.V.D., I also worked through the problem. I just wanted to post the simple but full example, for anyone wanting to review in the future.
public class App {
private static String OUTPUT_PATH = "D:\\so52875145\\output\\PdfWithPngImage.pdf";
public static void main(String[] args) {
try {
// obtain the SVG source (hardcoded here, but the OP would obtain the String from form data)
byte[] svgByteArray = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><polygon points=\"200,10 250,190 160,210\" style=\"fill:lime;stroke:purple;stroke-width:1\" /></svg>".getBytes();
System.out.println("Converted svg to byte array...");
// convert SVG into PNG image
PNGTranscoder pngTranscoder = new PNGTranscoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pngTranscoder.transcode(new TranscoderInput(new ByteArrayInputStream(svgByteArray)), new TranscoderOutput(os));
System.out.println("Transcoded svg to png...");
// create PDF, and add page to it
PDDocument pdf = new PDDocument();
pdf.addPage(new PDPage());
// generate in-memory PDF image object, using the transcoded ByteArray stream
BufferedImage bufferedImage = ImageIO.read( new ByteArrayInputStream(os.toByteArray()) );
PDImageXObject pdImage = LosslessFactory.createFromImage(pdf, bufferedImage);
System.out.println("Created PDF image object...");
// write the in-memory PDF image object to the PDF page
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(0));
contents.drawImage(pdImage, 0, 0);
contents.close();
System.out.println("Wrote PDF image object to PDF...");
pdf.save(OUTPUT_PATH);
pdf.close();
System.out.println("Saved PDF to path=[" + OUTPUT_PATH + "]");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Write Heart Symbol in pdf using itext java

Trying to write heart symbol in pdf through java code .
This is my input to pdf : ❤️❤️❤️
But pdf generated is empty without anything written.
Using itext to write to pdf.
The Font used is tradegothic_lt_boldcondtwenty.ttf
OutputStream file = new FileOutputStream(fileName);
Document document = new Document(PageSize.A6);
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
PdfLayer nested = new PdfLayer("Layer 1", writer);
PdfContentByte cb = writer.getDirectContent();
cb.beginLayer(nested);
ColumnText ct = new ColumnText(cb);
Font font = getFont();
Phrase para1 = new Phrase("❤️❤️❤️",font);
ct.setSimpleColumn(para1,38,0,260,138,15, Element.ALIGN_LEFT);
ct.go();
cb.endLayer();
document.close();
file.close();
private Font getFont() {
final String methodName = "generatePDF";
LOGGER.entering(CLASSNAME, methodName);
Font font = null;
try {
String filename = tradegothic_lt_boldcondtwenty.ttf;
FontFactory.register(filename, filename);
font = FontFactory.getFont(filename, BaseFont.CP1252, BaseFont.EMBEDDED,11.8f);
} catch(Exception exception) {
LOGGER.logp(Level.SEVERE, CLASSNAME, methodName, "Exception Occurred while fetching the Trade Gothic font." + exception);
font = FontFactory.getFont(FontFactory.HELVETICA_BOLD,11.8f);
}
return font;
}
Phrase para1 has the heart correctly. But not able to see in pdf

Convert html source to pdf using iText

I have an html file, which is generated as a response by my site.
While opening the html file in my browser, all the images and other elements are displaying properly. Moreover, I want to convert this html file into a pdf file.
So am using iText API to generate the pdf file.
In the html file images and texts are located horizontally.
But in the generated pdf output the images are displaying vertically.
code
String k = convertString();
OutputStream file = new FileOutputStream(new File("f:\\Test.pdf"));
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
InputStream is = new ByteArrayInputStream(k.getBytes());
XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
document.close();
file.close();
private static String convertString() {
StringBuilder contentBuilder = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new FileReader("f://testPage.html"));
String str;
while ((str = in.readLine()) != null) {
contentBuilder.append(str);
}
in.close();
} catch (IOException e) {
}
String content = contentBuilder.toString();
return content;
}
How can I generate a pdf that looks exactly the same as the appearance of the html UI?
Also, in Jfiddle, the html page is not displaying properly. What am I missing? Is the problem with my HTML, or is there some deeper issue with Jfiddle or something else at work?

Save a TextArea as PDF using Java 8 and PDFBox

I am trying to save a TextArea as PDF using PDFBox with Java 8. The file gets saved fine and open fine as well. But the file stores the TextArea as one line. I tried to split the TextArea and loop through it with drawString on each split but it's still not working.
Code:
public void saveOutput(MouseEvent e) throws IOException, COSVisitorException {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("PDF file(*.pdf)", " *.pdf");
fileChooser.getExtensionFilters().add(extFilter);
File savedFile = fileChooser.showSaveDialog(Controller.stage);
if (savedFile != null) {
PDDocument doc = null;
PDPage page = null;
doc = new PDDocument();
page = new PDPage();
doc.addPage(page);
PDFont font = PDType1Font.HELVETICA_BOLD;
PDPageContentStream content = new PDPageContentStream(doc, page);
content.beginText();
content.setFont(font, 8);
content.moveTextPositionByAmount(100, 700);
for (String line : d1CheckedOut.getText().split("\\R+")) {
System.out.println(line+"new line");
content.drawString(line+"\n");
}
content.endText();
content.close();
doc.save(savedFile);
doc.close();
}
}

Categories