I am using iTextPdf 5.5.3 to create PDF/A documents, I want the user to select custom fonts by uploading the .ttf file of the font, and becuase FontFactory.getFont() method only takes the font name as a string I have to write the uploaded file to the user's drive (I KNOW, I ASKED MY CUSTOMER FOR PERMISSION TO WRITE TO THE DRIVE) and then pass the path of the uploaded file to the getFont() method, after everything is finished I want to delete the uploaded files from the drive. Here is my code:
File fontFile = new File("d:/temp/testFont.ttf");
try {
FileOutputStream outStream = new FileOutputStream(fontFile);
outStream.write(the bytes of the uploaded font file);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Font font = FontFactory.getFont(fontFile.getAbsolutePath(), BaseFont.CP1250 , BaseFont.EMBEDDED);
fontFile.delete();
This code is not working, somehow the getFont() method is locking the font file and therefore the file is not being deleted. I tried lots of ways to do this, like: fontFile.deleteOnExit(); or FileDeleteStrategy.FORCE.delete("file path"); but nothing is working for me. Please advise. Thanks
I am not going to answer the question mentioned in the title of your post (because it is a secondary). Instead I am going to answer the question in the body (which is the essential question).
You claim that FontFactory.getFont() requires a font file on the file system. That is not incorrect. However, that doesn't mean you can't create a font from a byte[].
You are trying to solve your problem by saving a ttf on disk (which is forbidden by your customer), but that isn't necessary. In a way, your customer is right: it's not a good idea to save the TTF as a temporary file on disk (which is why I'm ignoring your secondary question).
Take a look at the following createFont() method:
public static BaseFont createFont(String name,
String encoding,
boolean embedded,
boolean cached,
byte[] ttfAfm,
byte[] pfb)
throws DocumentException,
IOException
This is how you should interpret the parameters in your case:
name - the name of the font (not the location)
encoding - the encoding to be applied to this font
embedded - true if the font is to be embedded in the PDF
cached - probably false in your case, as you won't be reusing the font in the JVM
ttfAfm - the bytes of the .ttf file
pfb - in your case, this value will benull (it only makes sense in the context of Type1 fonts).
Now you can meet the requirements of your customer and you do not need to introduce a suboptimal workaround.
Note: you are using iText 5.5.3 which is available under the AGPL. Please be aware that your customer will need to purchase a commercial license with iText Software as soon as he starts using iText in a web service, in a product,...
Related
I have managed to create my own pdf documents with the help of PdfDocument Class.
But what if I already have a pdf in my (let's say) assets folder and I want to e.g. draw something on it. Is it possible?
I have my
PdfDocument document;
But how can i read the powerpoint i have inside my project?
I am guessing i have to use a File but i cannot work this out.
I tried something like this, although I know it is wrong
PdfDocument document = new PdfDocument(getAssets().open("powerpoint"));
From what I understand you ask two questions:
But what if I already have a pdf in my (let's say) assets folder and I
want to e.g. draw something on it. Is it possible?
With the android PdfDocument class, you can create a PDF out of Web content (via WebView), a Canvas (using views or the native Canvas drawing API), or an image. You have to use third-party PDF libraries (like iText or the PDFBox Android port) to change existing PDFs.
But how can i read the powerpoint i have inside my project?
For displaying powerpoint there is a separate project called 'pptviewer-android'. However it is not maintained anymore, so if you have problems you probably have to figure those out by yourself. An examplary use can be found here.
PPTViewer pptViewer = (PPTViewer) findViewById(R.id.pptviewer);
pptViewer.setNext_img(R.drawable.next)
.setPrev_img(R.drawable.prev)
.setSettings_img(R.drawable.settings)
.setZoomin_img(R.drawable.zoomin)
.setZoomout_img(R.drawable.zoomout);
pptViewer.loadPPT(this,"/home/powerpoint.pptx");
Not sure whether I have correctly understood your problem statement:
Please try this out:
if (Desktop.isDesktopSupported()) {
try {
File fileToOpen = new File("/assets/file.pdf");
Desktop.getDesktop().open(fileToOpen);
} catch (IOException ex) {
// log Error
}
}
I would like to be able to upload files in my JSF2.2 web application, so I started using the new <h:inputFile> component.
My only question is, how can I specify the location, where the files will be saved in the server? I would like to get hold of them as java.io.File instances. This has to be implemented in the backing bean, but I don't clearly understand how.
JSF won't save the file in any predefined location. It will basically just offer you the uploaded file in flavor of a javax.servlet.http.Part instance which is behind the scenes temporarily stored in server's memory and/or temporary disk storage location which you shouldn't worry about.
Important is that you need to read the Part as soon as possible when the bean action (listener) method is invoked. The temporary storage may be cleared out when the HTTP response associated with the HTTP request is completed. In other words, the uploaded file won't necessarily be available in a subsequent request.
So, given a
<h:form enctype="multipart/form-data">
<h:inputFile value="#{bean.uploadedFile}">
<f:ajax listener="#{bean.upload}" />
</h:inputFile>
</h:form>
You have basically 2 options to save it:
1. Read all raw file contents into a byte[]
You can use InputStream#readAllBytes() for this.
private Part uploadedFile; // +getter+setter
private String fileName;
private byte[] fileContents;
public void upload() {
fileName = Paths.get(uploadedFile.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
try (InputStream input = uploadedFile.getInputStream()) {
fileContents = input.readAllBytes();
}
catch (IOException e) {
// Show faces message?
}
}
Note the Path#getFileName(). This is a MSIE fix as to obtaining the submitted file name. This browser incorrectly sends the full file path along the name instead of only the file name.
In case you're not on Java 9 yet and therefore can't use InputStream#readAllBytes(), then head to Convert InputStream to byte array in Java for all other ways to convert InputStream to byte[].
Keep in mind that each byte of an uploaded file costs one byte of server memory. Be careful that your server don't exhaust of memory when users do this too often or can easily abuse your system in this way. If you want to avoid this, better use (temporary) files on local disk file system instead.
2. Or, write it to local disk file system
In order to save it to the desired location, you need to get the content by Part#getInputStream() and then copy it to the Path representing the location.
private Part uploadedFile; // +getter+setter
private File savedFile;
public void upload() {
String fileName = Paths.get(uploadedFile.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
savedFile = new File(uploads, fileName);
try (InputStream input = file.getInputStream()) {
Files.copy(input, savedFile.toPath());
}
catch (IOException e) {
// Show faces message?
}
}
Note the Path#getFileName(). This is a MSIE fix as to obtaining the submitted file name. This browser incorrectly sends the full file path along the name instead of only the file name.
The uploads folder and the filename is fully under your control. E.g. "/path/to/uploads" and Part#getSubmittedFileName() respectively. Keep in mind that any existing file would be overwritten, you might want to use File#createTempFile() to autogenerate a filename. You can find an elaborate example in this answer.
Do not use Part#write() as some prople may suggest. It will basically rename the file in the temporary storage location as identified by #MultipartConfig(location). Also do not use ExternalContext#getRealPath() in order to save the uploaded file in deploy folder. The file will get lost when the WAR is redeployed for the simple reason that the file is not contained in the original WAR. Always save it on an absolute path outside the deploy folder.
For a live demo of upload-and-preview feature, check the demo section of the <o:inputFile> page on OmniFaces showcase.
See also:
Write file into disk using JSF 2.2 inputFile
How to save uploaded file in JSF
Recommended way to save uploaded files in a servlet application
I am having a situation where i receive a ms-word (docx) document as a stream/bytearray from a webservice.
I then try to recreate the file, giving it the same name and content as before.
If i compare the original file and the one created after the download, then they are identical.
However, when i try to open the new one in word i get an error, and if accept the riscs i can open it.
If i look at the properties af the file in windows, the new one is missing a lot of information.
Any one know how to recreate the properties so the file can be opened without errors?
Just an extra piece of information.. If i use .doc (word97-2003) documents all is working fine, only .docx documents are a problem (also .xlsx and all the office 2007-2010 documents).
This is my code creating the files..
private static void saveBytesAsFile(String path, String filename, byte[] data){
try {
File dir = new File(path);
dir.mkdirs();
OutputStream os = new FileOutputStream(path + "/" + filename);
os.write(data);
os.flush();
os.close();
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
I compared the original and the recreated file in notepad++, and got the result that they are identical.
This is how i see that some properties are missing.
Image of properties
These are the warnings i get from word:
If i press ok on the first and yes on the second i can open the document anyway.
Word Warnings
If you are asked to "accept the risks" then this sounds more like the default Word behaviour when downloading documents from the internet, not an error. You can change the Word behaviour from the Word Options, Trust Center (assuming you are using Word 2007 or later).
So I doubt that the missing properties are an issue. It is possible to change the creation date of the document that you are re-creating, by changing the system clock before building your new document (based on the previous document's content). I am not recommending these steps.
SOLUTION
It turned out that there were no problem with the properties.
It was simply so that somewhere in the services that provided the document data an extra blank character was added at the end of the file data.
This resulted in a mismatch of the expected file length and the actual one, and therefore the office components complained when trying to open the documents.
And this also prevented the properties of the file to be parsed.
What was pretty annoying, was that file comparison tools did not catch this. (Or maybe there need to be some configuration of trailing spaces not beeing ignored.)
I followed this tutorial for uploading a file in my JSF2 application.
The application works fine but I am unhappy with one aspect.
While rebuilding the request, the File sent via request is saved somewhere on the disk.
Even though the file is saved I need to rename the file with a name which is available after entering the Managed Bean containing the action method.
Therefore I decided to create a new file with de desired name, copy the already saved file, and then delete the unneeded one.
private File uploadFile;
//...
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(newFile));
BufferedReader br = new BufferedReader(new FileReader(uploadFile));
String line = "";
while ((line = br.readLine()) != null){
bw.write(line);
}
} catch (Exception e){}
The new file appears in the desired location but this error is thrown when I'm trying to open the file: "Invalid or unsupported PNG file"
These are my questions:
Is there a better way to solve this problem?
Is this solution the best way to upload a picture? Is there a reason to save the file before the business logic when there may be need to resize the picture or the desired name is not available yet.
LE:
I know abot this tutorial as well but I'm trying to do this mojarra only.
There is a rename method built into java.io.File object already, I'd be surprised if it didn't work for your situation.
public boolean renameTo(File dest)
Renames the file denoted by this abstract pathname.
Many aspects of the behavior of this method are inherently platform-dependent:
The rename operation might not be able to move a file from one filesystem to
another, it might not be atomic, and it might not succeed if a file with the
destination abstract pathname already exists. The return value should always
be checked to make sure that the rename operation was successful.
You can also check if a file exists before saving it, and you can use the ImageIO class to do validations on the uploaded file before performing the initial save.
Don't use Reader and Writer when you deal with binary files like images. Use streams: FileInputStream and FileOutputStream. And the best variant is to use #Perception solution with renameTo method.
Readers read file as if it consists of characters (e.g. txt, properties, yaml files). Image files are not characters, they are binary and you must use streams for that.
Does anyone know of a way to detect whether a given PDF file is a PDF Portfolio or a PDF Package, rather than a "regular" PDF? I'd prefer Java solutions, although since I haven't yet found any information on detecting the specific type of PDF, I'll take what I can get and they try to figure out the Java solution afterwards.
(In searching past questions, it appears that a bunch of folks don't know that such things as PDF Portfolios and PDF Packages exist. Generally, they're both ways that Adobe allows multiple, discrete PDFs to be packaged into a single PDF file. Opening a PDF Package in Reader shows the user a list of the embedded PDFs and allows further viewing from there. PDF Portfolios appear to be a bit more complicated -- they also include Flash-based browser for the embedded files, and then allow users to extract the discrete PDFs from there. My issue with them, and the reason I'd like to be able to detect them in code, is because OS X's built-in Preview.app can't read these files -- so I'd like to at least warn users of a web app of mine that uploading them can lead to diminished compatibility across platforms.)
This question is old, but in-case someone wants to know, it is possible. It can be done with Acrobat and JavaScript by using the following command.
if (Doc.collection() != null)
{
//It Is Portfolio
}
Acrobat JavaScript API says, "A collection object is obtained from the Doc.collection property. Doc.collection returns a null value when there is no PDF collection (also called PDF package and PDF portfolio).The collection object is used to set the initial document in the collection, set the initial view of the collection, and to get, add, and remove collection fields (or categories)."
I'm also facing same problem while extracting data through kofax, but i got solution and its working fine need to add extra jar for Document class.
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class PDFPortfolio {
/**
* #param args
*/
public static void main(String[] args) {
com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document("e:/pqr1.pdf");
// get collection of embedded files
com.aspose.pdf.EmbeddedFileCollection embeddedFiles = pdfDocument.getEmbeddedFiles();
// iterate through individual file of Portfolio
for(int counter=1; counter<=pdfDocument.getEmbeddedFiles().size();counter++)
{
com.aspose.pdf.FileSpecification fileSpecification = embeddedFiles.get_Item(counter);
try {
InputStream input = fileSpecification.getContents();
File file = new File(fileSpecification.getName());
// create path for file from pdf
// file.getParentFile().mkdirs();
// create and extract file from pdf
java.io.FileOutputStream output = new java.io.FileOutputStream("e:/"+fileSpecification.getName(), true);
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = input.read(buffer)))
output.write(buffer, 0, n);
// close InputStream object
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}