Properties missing in docx file - java

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.)

Related

File/ontology (turtle, N3, JSON, RDF-XML) etc to .ttl file conversions in java

I wanted to ask if there is a way in Java where I can read in, basically any file format (N3, JSON, RDF-XML) etc and then convert it into turtle(.ttl). I have searched on Google to get some idea, but they mainly just explain for specific file types and how a file type can be converted to RDF whereas I want it the other way.
EDIT (following the code example given in the answer):
if(FilePath.getText().equals("")){
FilePath.setText("Cannot be empty");
}else{
try {
// get the inputFile from file chooser and setting a text field with
// the path (FilePath is the variable name fo the textField in which the
// path to the selected file from file chooser is done earlier)
FileInputStream fis = new FileInputStream(FilePath.getText());
// guess the format of the input file (default set to RDF/XML)
// when clicking on the error I get take to this line.
RDFFormat inputFormat = Rio.getParserFormatForFileName(fis.toString()).orElse(RDFFormat.RDFXML);
//create a parser for the input file and a writer for Turtle
RDFParser rdfParser = Rio.createParser(inputFormat);
RDFWriter rdfWriter = Rio.createWriter(RDFFormat.TURTLE,
new FileOutputStream("./" + fileName + ".ttl"));
//link parser to the writer
rdfParser.setRDFHandler(rdfWriter);
//start the conversion
InputStream inputStream = fis;
rdfParser.parse(inputStream, fis.toString());
//exception handling
} catch (FileNotFoundException ex) {
Logger.getLogger(FileConverter.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(FileConverter.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have added "eclipse-rdf4j-3.0.3-onejar.jar" to the Libraries folder in NetBeans and now when I run the program I keep getting this error:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at org.eclipse.rdf4j.common.lang.service.ServiceRegistry.(ServiceRegistry.java:31)
Any help or advice would be highly appreciated. Thank you.
Yes, this is possible. One option is to use Eclipse RDF4J for this purpose, or more specifically, its Rio parser/writer toolkit.
Here's a code example using RDF4J Rio. It detects the syntax format of the input file based on the file extension, and directly writes the data to a new file, in Turtle syntax:
// the input file
java.net.URL url = new URL(“http://example.org/example.rdf”);
// guess the format of the input file (default to RDF/XML)
RDFFormat inputFormat = Rio.getParserFormatForFileName(url.toString()).orElse(RDFFormat.RDFXML);
// create a parser for the input file and a writer for Turtle format
RDFParser rdfParser = Rio.createParser(inputFormat);
RDFWriter rdfWriter = Rio.createWriter(RDFFormat.TURTLE,
new FileOutputStream("/path/to/example-output.ttl"));
// link the parser to the writer
rdfParser.setRDFHandler(rdfWriter);
// start the conversion
try(InputStream inputStream = url.openStream()) {
rdfParser.parse(inputStream, url.toString());
}
catch (IOException | RDFParseException | RDFHandlerException e) { ... }
For more examples, see the RDF4J documentation.
edit Regarding your NoClassDefFoundError: you're missing a necessary third party library on your classpath (in this particular case, a logging library).
Instead of using the onejar, it's probably better to use Maven (or Gradle) to set up your project. See the development environment setup notes, or for a more step by step guide, see this tutorial (the tutorial uses Eclipse rather than Netbeans, but the points about how to set up your maven project will be very similar in Netbeans).
If you really don't want to use Maven, what you can also do is just download the RDF4J SDK, which is a ZIP file. Unpack it, and just add all jar files in the lib/ directory to Netbeans.
An other option would be to use Apache Jena.

How can fix this error while trying to upload a file to a online database using JSF 2.2? [duplicate]

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

How to check whether file is open or not in java [duplicate]

I need to write a custom batch File renamer. I've got the bulk of it done except I can't figure out how to check if a file is already open. I'm just using the java.io.File package and there is a canWrite() method but that doesn't seem to test if the file is in use by another program. Any ideas on how I can make this work?
Using the Apache Commons IO library...
boolean isFileUnlocked = false;
try {
org.apache.commons.io.FileUtils.touch(yourFile);
isFileUnlocked = true;
} catch (IOException e) {
isFileUnlocked = false;
}
if(isFileUnlocked){
// Do stuff you need to do with a file that is NOT locked.
} else {
// Do stuff you need to do with a file that IS locked
}
(The Q&A is about how to deal with Windows "open file" locks ... not how implement this kind of locking portably.)
This whole issue is fraught with portability issues and race conditions:
You could try to use FileLock, but it is not necessarily supported for your OS and/or filesystem.
It appears that on Windows you may be unable to use FileLock if another application has opened the file in a particular way.
Even if you did manage to use FileLock or something else, you've still got the problem that something may come in and open the file between you testing the file and doing the rename.
A simpler though non-portable solution is to just try the rename (or whatever it is you are trying to do) and diagnose the return value and / or any Java exceptions that arise due to opened files.
Notes:
If you use the Files API instead of the File API you will get more information in the event of a failure.
On systems (e.g. Linux) where you are allowed to rename a locked or open file, you won't get any failure result or exceptions. The operation will just succeed. However, on such systems you generally don't need to worry if a file is already open, since the OS doesn't lock files on open.
// TO CHECK WHETHER A FILE IS OPENED
// OR NOT (not for .txt files)
// the file we want to check
String fileName = "C:\\Text.xlsx";
File file = new File(fileName);
// try to rename the file with the same name
File sameFileName = new File(fileName);
if(file.renameTo(sameFileName)){
// if the file is renamed
System.out.println("file is closed");
}else{
// if the file didnt accept the renaming operation
System.out.println("file is opened");
}
On Windows I found the answer https://stackoverflow.com/a/13706972/3014879 using
fileIsLocked = !file.renameTo(file)
most useful, as it avoids false positives when processing write protected (or readonly) files.
org.apache.commons.io.FileUtils.touch(yourFile) doesn't check if your file is open or not. Instead, it changes the timestamp of the file to the current time.
I used IOException and it works just fine:
try
{
String filePath = "C:\sheet.xlsx";
FileWriter fw = new FileWriter(filePath );
}
catch (IOException e)
{
System.out.println("File is open");
}
I don't think you'll ever get a definitive solution for this, the operating system isn't necessarily going to tell you if the file is open or not.
You might get some mileage out of java.nio.channels.FileLock, although the javadoc is loaded with caveats.
Hi I really hope this helps.
I tried all the options before and none really work on Windows. The only think that helped me accomplish this was trying to move the file. Event to the same place under an ATOMIC_MOVE. If the file is being written by another program or Java thread, this definitely will produce an Exception.
try{
Files.move(Paths.get(currentFile.getPath()),
Paths.get(currentFile.getPath()), StandardCopyOption.ATOMIC_MOVE);
// DO YOUR STUFF HERE SINCE IT IS NOT BEING WRITTEN BY ANOTHER PROGRAM
} catch (Exception e){
// DO NOT WRITE THEN SINCE THE FILE IS BEING WRITTEN BY ANOTHER PROGRAM
}
If file is in use FileOutputStream fileOutputStream = new FileOutputStream(file); returns java.io.FileNotFoundException with 'The process cannot access the file because it is being used by another process' in the exception message.

Can't delete file after calling FontFactory.getFont() method

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,...

How to move/rename uploaded file?

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.

Categories

Resources