I have a requirement to generate PDF file from JSON Objects and am able to produce PDF document using Apache FOP and Java. But i want to return the PDF file as ByteArrayOutputStream and then i have to encode like this Base64.getEncoder().encodeToString(baos.toByteArray()).
Please find the below code where am able to generate PDF file, instead of FileOutputStream i want to return as ByteArrayOutputStream.
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
Transformer xslfoTransformer;
try
{
xslfoTransformer = getTransformer(transformSource);
Fop fop;
try
{
fop = fopFactory.newFop
(MimeConstants.MIME_PDF, outStream);
Result res = new SAXResult(fop.getDefaultHandler());
ITextRenderer renderer = new ITextRenderer();
try
{
xslfoTransformer.transform(source, res);
File pdffile = new File("Result.pdf");
OutputStream out = new java.io.FileOutputStream(pdffile);
out = new java.io.BufferedOutputStream(out);
FileOutputStream str = new FileOutputStream(pdffile);
str.write(outStream.toByteArray());
str.close();
out.close();
}
catch (TransformerException e) {
throw e;
}
}
catch (FOPException e) {
throw e;
}
}
catch (TransformerConfigurationException e)
{
throw e;
}
catch (TransformerFactoryConfigurationError e)
{
throw e;
}
I am slightly confused to what you are asking.
I have not used Apache Fop, but will try answer this question.
If you want to read PDF file as byte array use input streams instead.
But if you want to use ByteArrayOutputStream that is writing bytes you basically answered your own question, try using existing BAOS that you created initially and you are using in FileOutputStream, that's assuming the byte array output stream is reading bytes via some InputStream or some other source. Second assumption is that BAOS and FOS were able to properly write PDF file you were talking about.
You can simply do:
byte[] b = outStream.toByteArray();
String str = Base64.getEncoder().encodeToString(b);
Related
I'm reading a file, adding some data to paragraphs, and then writing out a document another file.
The problem I'm facing is that the output file is unreadable, I can't open it, and if a binary open it I can see that it don't have the correct format.
Every character has a ? character at the left side.
Can you give me some advice about what is happening?
Wrong output
Correct output
EDIT: Code Save function
FileOutputStream out = null;
try {
// Add true to make the data append possible in output stream.
out = new FileOutputStream(filePath, true);
doc.write(out);
out.flush();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
out.close();
}
Edit file:
File file = new File("muestra.doc");
FileInputStream fis = new FileInputStream(file.getAbsolutePath());
POIFSFileSystem fs = new POIFSFileSystem(fis);
HWPFDocument document = new HWPFDocument(fs);
Range range = document.getRange();
for (int i = 0; i < document.getParagraphTable().getParagraphs().size(); i++) {
Paragraph p = range.getParagraph(i);
p.insertBefore("£");
}
I have a function which creates a Zip file from a list of files. Is it possible to return the Zip file without it being saved on the disk? I need the file as I have to use the zip file as a parameter for another function. I am not sure of the ByteStream would be an option for me.
public File compressFileList(List<File> fileList,String fileName) {
FileOutputStream fileOutputStream=null;
ZipOutputStream zipOutputStream=null;
FileInputStream fileInputStream=null;
String compressedFileName=fileName +".zip";
if(fileList.isEmpty())
return null;
try
{
fileOutputStream = new FileOutputStream(compressedFileName);
zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
for (File file: fileList) {
fileInputStream = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] tmp = new byte[4*1024];
int size = 0;
while((size = fileInputStream.read(tmp)) != -1){
zipOutputStream.write(tmp, 0, size);
}
zipOutputStream.flush();
fileInputStream.close();
}
zipOutputStream.close();
return compressedFile; //This is what I am missing
}
catch (FileNotFoundException e)
{
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
EDIT : adding the use case
The idea is to create a zip file and use the CreateClassifierOptions method of VisualRecognition Service of Watson.
classifierOptions = new CreateClassifierOptions.Builder()
.classifierName("Santa")
.addClass("Santa", new File("C:\\app\\GitRepo\\images\\beagle.zip"))
.negativeExamples(new File("C:\\app\\GitRepo\\images\\nosport.zip"))
.build();
The builder accepts the zip file as the parameter.
Understanding
Based on the explanation from Alexandre Dupriez, I think it is better to store the file at some place on the hard disk.
You should be able to use a ByteArrayOutputStream instead of a FileOutputStream:
zipOutputStream = new ZipOutputStream(new ByteArrayOutputStream());
The difficulty here is to provide a File to the method consuming the zip file. The java.io.File does not provide an abstraction which allows you to manipulate in-memory files.
The java.io.File abstraction and java.io.FileInputStream implementation
To simplify, if we had to boil down what the File abstraction is, we would see it as a URI. And therefore, to be able to build an in-memory File, or at least mimic it, we would need to provide an URI which would then be used by the consumer of the File to read its content.
If we look at the FileInputStream which the consumer is likely to use, we can see that it always ends up with a native call which gives us to possibility whatsoever to abstract a FileSystem for in-memory files:
// class java.io.FileInputStream
/**
* Opens the specified file for reading.
* #param name the name of the file
*/
private native void open0(String name) throws FileNotFoundException;
It would be easier if there was a possibility to adapt the consumer to accept an InputStream, but from your problem statement I guess this is not possible.
API call
Your requirement is to provide a File to the Watson Visual API.
Could you please provide the API method you need to call?
public void compressFileList(List<File> fileList, OutputStream outputStream)
throws IOException {
try (ZipOutputStream zipOutputStream =
new ZipOutputStream(new BufferedOutputStream(outputStream));
for (File file: fileList) {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
byte[] tmp = new byte[4*1024];
int size = 0;
while((size = fileInputStream.read(tmp)) != -1){
zipOutputStream.write(tmp, 0, size);
}
zipOutputStream.flush();
} catch (FileNotFoundException e) { // Maybe skip not found files.
Logger.log(Level.INFO, "File not found {}", file.getPath());
}
}
}
}
Usage:
if (fileList.isEmpty()) {
...
return;
}
try {
compressFileList(fileList, servletRequest.getOutputStream())) {
} catch (FileNotFoundException e) {
...
} catch (IOException e) {
...
}
I have a File that I would like to update based on some user menu selection.
My code gets the IFile
if it does not exist it's been created (with the user's content),and if it exists it should be updated.
My current code is:
String userString= "original String"; //This will be set by the user
byte[] bytes = userString.getBytes();
InputStream source = new ByteArrayInputStream(bytes);
try {
if( !file.exists()){
file.create(source, IResource.NONE, null);
}
else{
InputStream content = file.getContents();
//TODO augment content
file.setContents(content, 1, null);
}
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
IDE.openEditor(page, file);
My problem is that even though I get the original content and set the file's content, I am getting an empty file upon update , i.e., the entire content is being deleted.
What am I doing wrong?
This version of the code in your comment works for me:
InputStream inputStream = file.getContents();
StringWriter writer = new StringWriter();
// Copy to string, use the file's encoding
IOUtils.copy(inputStream, writer, file.getCharset());
// Done with input
inputStream.close();
String theString = writer.toString();
theString = theString + " added";
// Get bytes using the file's encoding
byte[] bytes = theString.getBytes(file.getCharset());
InputStream source = new ByteArrayInputStream(bytes);
file.setContents(source, IResource.FORCE, null);
Note the close of the original input stream and the use of file.getCharset() to use the correct encoding.
I'm trying to delete a PDF file after printing. The PDF is generated using JAVA code and needs to be deleted after the printing process is carried out. However, I am facing an issue while deleting the file. I can't seem to figure out what the problem is.
The error shown while trying to delete the file from its folder is:
"File in Use: The Action can't be completed because the file is open in Java(TM) Platform SE Binary."
The code I've used is as follows:
public String actionPrintReport() {
try {
// Creates a new document object
Document document = new Document(PageSize.LETTER);
File file = new File(fileLocation.concat("\\".concat(fileName)));
FileOutputStream fo = new FileOutputStream(file);
// Creates a pdfWriter object for the FILE
PdfWriter pdfWriter = PdfWriter.getInstance(document, fo);
// Open the document
document.open();
// Add meta data...
// Insert Data...
// Close the document
document.close();
// Create a PDFFile from a File reference
FileInputStream fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
PDFFile pdfFile = new PDFFile(bb);
// Create PDF Print Page
PDFPrintPage pages = new PDFPrintPage(pdfFile);
// Create Print Job...
// Close
fo.flush();
fo.close();
fis.close();
if (file.exists()) {
if (file.delete()) {
String check = "yes";
} else {
String check = "no";
}
}
// Send print job to default printer
pjob.print();
actionMsg = "success";
return SUCCESS;
} catch (Exception e) {
e.printStackTrace();
}
return ERROR;
}
why not put the deletion in a finally block?
} catch (Exception e) {
e.printStackTrace();
} finally {
if (file.exists()) {
file.delete();
}
}
After discussion with the OP, an approach was investigated to use Apache FileCleaningTracker whereby the File is tracked and then deleted after a Monitored Object has been GC'd.
I need a little help here with my PDF converter program.
So, I'm doing this mobile agent PDF converter using JADE framework. But, the problem that I am facing is more related to the way I convert a text file into PDF, send it across network as binary and restore PDF file back.
The program that I've written works properly on my MacBook.
But, on a Windows, it restores my PDF file as an empty PDF.
Here is my code that I use for sending the PDF file across.
private void sendPDF(File f, String recipient) {
String content = "";
if(f != null) {
try {
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int noBytesRead = 0;
byte[] buffer = new byte[1024];
while((noBytesRead = fis.read(buffer)) != -1) {
baos.write(buffer, 0, noBytesRead);
}
content = baos.toString();
fis.close();
baos.close();
System.out.println("Successful PDF-to-byte conversion.");
} catch (Exception e) {
System.out.println("Exception while converting PDF-to-byte.");
content = "failed";
e.printStackTrace();
}
} else {
System.out.println("PDF-to-file conversion failed.");
content = "failed";
}
ACLMessage message = new ACLMessage(ACLMessage.INFORM);
message.addReceiver(new AID(recipient, AID.ISLOCALNAME));
message.setContent(content);
myAgent.send(message);
System.out.println("PDF document has been sent to requesting client.");
}
And, here is the code that I use to restore the PDF back.
private File restorePDF(String content) {
String dirPDF = dirBuffer + "/" + new Date().getTime() + ".pdf";
File f = new File(dirPDF);
try {
if(!f.exists()) f.createNewFile();
byte[] buffer = new byte[1024];
ByteArrayInputStream bais = new ByteArrayInputStream(content.getBytes());
FileOutputStream fos = new FileOutputStream(f);
int noBytesRead = 0;
while((noBytesRead = bais.read(buffer)) != -1) {
fos.write(buffer, 0, noBytesRead);
}
fos.flush();
fos.close();
bais.close();
} catch (Exception e) {
e.printStackTrace();
f = null;
}
return f;
}
Any help on this would be much appreciated! :)
Question is a little bit confusing, since there is nothing specific about PDF content.
I am supposing you actually want to send bytes, actually send a string, and the string encoding is different on the client and server.
This is usually where troubles happen:
content = baos.toString();
and:
content.getBytes()
A PDF file is a binary file format with lookup tables and lots of binary data blocks to making it a String will break it. If you want to know about the insides of a PDF file, I have written a whole load of blog posts about it (http://www.jpedal.org/PDFblog/2010/09/understanding-the-pdf-file-format-series/)
One issue is that you're using the wrong separator char. Java has a built in function that will return the correct char for the correct os. See separator char.
Your code will look something like this
String dirPDF = dirBuffer + File.separatorChar + new Date().getTime() + ".pdf";
For reference:
separatorChar
The system-dependent default name-separator character. This field is
initialized to contain the first character of the value of the system
property file.separator. On UNIX systems the value of this field is
'/'; on Microsoft Windows systems it is '\'.