We are noticing unwanted behaviour with uploading files via xp:fileUpload control. sometimes users get files from other users uploaded.
the files are named the same but the content differes.
I was using:
File correctedFile = new File(tempFile.getParentFile() + File.separator + tempClientFile);
to create a file in Notes document from uploaded file.
I noticed in some other code from others the following was used:
File correctedFile = new File( serverFile.getParentFile().getAbsolutePath() + File.separator + fileName );
Can the lacking of absolutepath can be the cause of file switch?
Ofcourse we have never noticed the occurrence under Testing in our Test environment.
.getAbsolutePath() returns the full path whereas .toString() which is implicit used in your case returns just the abstract path.
Here is a description of the difference.
I use .getAbsolutePath() in my Domino backend code and never experienced the issue you describe.
Related
i'm using OutputStream to create a pdf file for download as follow:
byte[] infoFile = info.getBytes();
String infoName = info.getFileName();
String contentType = info.getContentType();
response.setContentType(contentType);
response.setHeader("Content-disposition", "attachment;filename=\"" + infoName + "\"");
response.setContentLength(infoFile.length);
// till now no problem, the file name is ok
OutputStream out = response.getOutputStream();
out.write(infoFile);
//here, as soon as the previous line is executed a file is generated with wrong characters
// ex. D:__Profiles__User__Downloads__infoFile.pdf
Here the file produced is something like "D:__Profiles__User__Downloads__infoFile.pdf"
while i expect the file "D:\Profiles\User\Downloads\infoFile.pdf"
What's wrong?
What's wrong?
Your expectation that the filename in a Content-disposition header should have path information.
From RFC 6266 section 4.3
Recipients MUST NOT be able to write into any location other than
one to which they are specifically entitled. To illustrate the
problem, consider the consequences of being able to overwrite
well-known system locations (such as "/etc/passwd"). One strategy
to achieve this is to never trust folder name information in the
filename parameter, for instance by stripping all but the last
path segment and only considering the actual filename (where 'path
segments' are the components of the field value delimited by the
path separator characters "" and "/").
And similarly in the Mozilla docs
The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done.
Basically you should only be specifying infoFile.pdf. It's up to the user which directory that file is saved in.
How would I convert the name of a file on the classpath to a real filename?
For example, let's say the directory "C:\workspace\project\target\classes" is on your classpath. Within that directory is a file, such as info.properties.
How would you determine (at runtime) the absolute file path to the info.properties file, given only the string "info.properties"?
The result would be something like "C:\workspace\project\target\classes\info.properties".
Why is this useful? When writing unit tests, you may want to access files bundled in your test resources (src/main/resources) but are working with a third-party library or other system that requires a true filename, not a relative classpath reference.
Note: I've answered this question myself, as I feel it's a useful trick, but it looks like no one has ever asked this question before.
Use a combination of ClassLoader.getResource() and URL.getFile()
URL url = Thread.currentThread().getContextClassLoader().getResource( resource );
if( url == null ){
throw new RuntimeException( "Cannot find resource on classpath: '" + resource + "'" );
}
String file = url.getFile();
Note for Windows: in the example above, the actual result will be
"/C:/workspace/project/target/classes/info.properties"
If you need a more Windows-like path (i.e. "C:\workspace\..."), use:
String nativeFilename = new File(file).getPath();
Im developing a servlet, and I have to copy a file (*.doc) from a shared folder in other computer to my servlet webapp space, but I can't. The trouble is not writing on my Apache Server, instead of, Im expecting troubles copying the file from the remote folder (shared folder in a LAN). Any suggest or idea?
File inFile = new File( "\\\\192.168.2.103\\CompartidaMatias\\tablaEstudios.txt");
out.println("<p> AbsolutePath --> " + inFile.getAbsolutePath() + "</p>");
out.println("<p> Path --> " + inFile.getPath() + "</p>");
out.println("<p> Nombre --> " + inFile.getName() + "</p>");
out.println("<p> WEBAPP_ROOT --> " + WEBAPP_ROOT + "</p>");
File outFile = new File(WEBAPP_ROOT + "mydoc3a.txt");
if (inFile.exists())
out.println("<p>FILE FOUND</p>");
else
out.println("<p>FILE NOT FOUND</p>");
I get always FILE NOT FOUND :(
Thanks for your time buddies!! I hope it could be solved, but I have spent all my ideas. Thanks again!!
This is not how java.io.File works. It works on the local disk file system only, not on network resources.
Your best bet is to let your operating system platform create a local mapping (kind of a virtual disk) pointing to the network resource and, given you're on Windows, assign it a disk letter as well. Here's a Microsoft Windows 7 guide on the subject:
You just have to map \\192.168.2.103 to e.g. Z:\. Once done that, you should be able to locate the file as follows:
new File("Z:/CompartidaMatias/tablaEstudios.txt");
(note that / works as good as \\ and saves you from effort of escaping them)
Note that this problem has completely nothing to do with servlets. It's just a basic Java problem. You'd have exactly the same problem when executing this in a plain Java application with a main() method (which by the way allows for so much faster and easier testing than a servlet). Keep this in mind for your future questions.
try:
URL url = new URL( "file:///192.168.2.103//CompartidaMatias//tablaEstudios.txt" );
File inFile = new File( url.getFile() );
I'm trying to list a directory's contents, and rename certain files.
public void run(String dirName) {
try {
File parDir = new File(dirName);
File[] dirContents = parDir.listFiles();
// Rename if necessary
for(File f : dirContents) {
System.out.println("f is:\n" + f.toString());
String name = f.getName();
String subbedName = name.replaceAll("\uFFFD", "_");
System.out.println("\n" + "name = " + name + ", subbedName = " + subbedName + "\n");
if(!name.equals(subbedName)) {
File newFile = new File(f.getParentFile(), subbedName);
System.out.println("newFile is:\n" + newFile.toString());
if(!f.renameTo(newFile))
System.out.println("Tried to change file name but couldn't.");
}
}
}
catch(Exception exc1) {
System.out.println("Something happened while listing and renaming directory contents: " + exc1.getMessage());
}
}
When I run this, I get "Tried to change file name but couldn't." I don't believe that Java is considering these files to be "open", so I don't think that's the reason. I've even ran chmod 777 myDir where myDir is the value of the dirName string passed into the run method.
What am I missing here? Why won't Java rename these file(s)? These are CentOS machines.
Edit: Added printouts for both f and newFile, which is as follows:
f is:
/root/path/to/mydir/test�.txt
newFile is:
/root/path/to/mydir/test_.txt
You need to create your new File object with the full pathname of those files. So
String name = f.getName(); // gets the name without the directory
should likely be:
String name = f.getAbsolutePath();
(your search/replace may need to change)
The problem is that f.getName() returns the last name component of the path that is represented by f. You then massage this String and turn it back into a File. But the File now represents a path relative to the current directory, not the directory containing the original path.
As a result your code is actually attempting to rename the files from dirName into the application's current directory. That could fail because files already exist in the current directory with those names, or because the dirName and the current directory are in different file systems. (You cannot rename a file from one filesystem to another ... you have to copy it.)
Please note that a File in Java represents a pathname, not a file or a folder. In your code, the f objects are the pathnames for file system objects (either files or folders) in the directory denoted by the String dirname. Each of these f objects will have a directory part.
There is more than one way to fix your code; for example
change name = f.getName() to name = f.toString()
change new File(subbedName) to new File(f.getParentFile(), subbedName)
I have an alternative / additional theory.
The pathname of the file containing the \uFFFD character is coming out as "mojibake"; i.e. the kind of garbled text that you get when you display encoded text using the wrong encoding. And since we are seeing 3 characters of garbled text, I suspect that it is attempting to display the UTF-8 rendering of \uFFFD as Latin-1.
So my theory is that the same think is happening when the File.renameTo method is converting f to the form that it is going to provide to the system call. For some reason that is no clear to me, Java could be using the wrong encoding, and as a result producing a "name" for the original file that doesn't match the name of the file in the file system. That would be sufficient to cause the rename to fail.
Possibly related questions / links:
File name charset problem in java
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4733494 (Note that Sun decided this was not a Java bug, and most of the "me too" comments on the bug report are from people who do not understand the explanation ...)
f.getName(); only returns the name of the folder, not the full path. So subbedName becomes a relative path file. Try something with f.getCanonicalPath() instead.
I am working on a web-based program, using Java. I am not sure exactly how to phrase this, but I expect the program to be running from within the c:/Resin/webapps/apps directory. However, when I reference a file in the program like this: "../files/randomfile.pdf", it cannot find that file. It works when I reference it like this: "c:/Resin/webapps/files/randomfile.pdf". How to I change the "running location"? (And what is the technical term for this?)
try {
Document iTextDoc = new Document(PageSize.LETTER, 27, 27, 35, 18);
HttpServletResponse res = (HttpServletResponse) pageContext.getResponse();
res.setContentType("application/vnd.ms-word");
res.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".rtf;");
RtfWriter2 rtfWriter = RtfWriter2.getInstance(iTextDoc, res.getOutputStream());
iTextDoc.open();
iTextDoc.add(new Paragraph ("Testing RTF Letterhead with Logo"));
// Use full classname to avoid ambiguity with java.awt.Image
com.lowagie.text.Image logoImg = com.lowagie.text.Image.getInstance("../files/someimage.jpg");
logoImg.setAlignment(Image.RIGHT | Image.TEXTWRAP);
iTextDoc.add(logoImg);
iTextDoc.add(new Paragraph ("Put other information about organization beneath logo"));
iTextDoc.close();
}
I get the following error with the resulting file: Adobe Reader could not open 'someFile.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).
However, if I change the getInstance command to this:
com.lowagie.text.Image logoImg = com.lowagie.text.Image.getInstance("webapps/files/someimage.jpg");
it works. So my guess is that the working directory (thanks for the term) needs to be set somewhere. I am using Resin -- any idea where I should be setting this?
Thanks!
You are probably referring to the user.dir system property, which is read only. Relative paths use this as the root folder.
In a java program you can't change the running location.
First you should find out where your program is running. You can do this by calling
System.out.println( new File( "." ).getAbsolutePath() );
Now you can specify your paths relative to this directory.
From the java.io.File doc
By default the classes in the java.io package always resolve relative pathnames against the current user directory. This directory is named by the system property user.dir, and is typically the directory in which the Java virtual machine was invoked.
Broadly speaking, you should not rely on the current directory for locating files. Use full (absolute) paths, if possible (but without harcoding it in you application, of course). if the file is inside a webapp tree (or just inside the classpath), you might want to take a look at findResource() and related methods.