My upload servlet keeps throwing me an exception saying that the file that I'm trying to replace (near the end of my code) could not be deleted at (seemingly) random. I don't know what's causing this since I'm not using any streams and the file isn't open in my browser. Does anyone know what could be causing this? I'm completely clueless on this one as the code seems correct to me. This is the first time I've used DiskFileItem so I'm not sure if there are any nuances to handle there.
Keep in mind that it sometimes works, sometimes doesn't. I'm lost on that.
Problem Area:
File destination = new File(wellnessDir + File.separator + fileName + ".pdf");
System.out.println("destination file exists: " + destination.exists());
System.out.println("file to be moved exists: " + uploadedFile.exists());
if(destination.exists()){
boolean deleted = destination.delete();
if(!deleted)
throw new Exception("Could not delete file at " + destination);
}
My System outs always say that both file and destination exist. I'm trying to get the upload to overwrite the existing file.
Full code: (& pastebin)
private void uploadRequestHandler(ServletFileUpload upload, HttpServletRequest request)
{
// Handle the request
String fileName = "blank";
try{
List items = upload.parseRequest(request);
//Process the uploaded items
Iterator iter = items.iterator();
File uploadedFile = new File(getHome() + File.separator + "temp");
if(uploadedFile.exists()){
boolean tempDeleted = uploadedFile.delete();
if(!tempDeleted)
throw new Exception("Existing temp file could not be deleted.");
}
//write the file
while (iter.hasNext()) {
DiskFileItem item = (DiskFileItem) iter.next();
if(item.isFormField()){
String fieldName = item.getFieldName();
String fieldValue = item.getString();
if(fieldName.equals("fileName"))
fileName = fieldValue;
//other form values would need to be handled here, right now only need for fileName
}else{
item.write(uploadedFile);
}
}
if(fileName.equals("blank"))
throw new Exception("File name could not be parsed.");
//move file
File wellnessDir = new File(getHome() + File.separator + "medcottage" + File.separator + "wellness");
File destination = new File(wellnessDir + File.separator + fileName + ".pdf");
System.out.println("destination file exists: " + destination.exists());
System.out.println("file to be moved exists: " + uploadedFile.exists());
if(destination.exists()){
boolean deleted = destination.delete();
if(!deleted)
throw new Exception("Could not delete file at " + destination);
}
FileUtil.move(uploadedFile, new File(wellnessDir + File.separator + fileName + ".pdf"));
writeResponse();
} catch (Exception e) {
System.out.println("Error handling upload request.");
e.printStackTrace();
}
}
edit: to add, getHome() and "home" aren't really in the code, that's just to protect my home path
After much testing and aggravation, finally tried it on a different machine, same code, worked great. Has something to do with me transferring domains on my work machine and it messing with permissions.
Related
I have an application which copies a number of files from a directory to a certain destination. The problem is that when you select a large folder it gets more intense for the app itself and then crashes. Is there any way to make it not crash? Maybe split it up into smaller parts?
This is my code:
public void startProcess(File orgDir, File destDir) {
Screen1Controller sf = new Screen1Controller();
String selectedExtension = sf.selectedExtension; // Gets selected extension from Screen1
String extensionType = sf.typeOfExtension; // Gets selected extension type from Screen1
int y = 1; // This is for searching for duplicates.. See below.
try {
File[] files = orgDir.listFiles();
for (File file : files) { // Goes through the files in the given directory
if (!file.isDirectory() && file.getName().endsWith(selectedExtension)){
File destinationPath = new File(destDir.getCanonicalPath() + "\\");
destDir = new File(destinationPath + "\\" + extensionType); // Sets the destination path
destDir.mkdir();
System.out.println("file:" + file.getCanonicalPath()); // Prints the file path
try{
String fileNameWithOutExt = file.getName().replaceFirst("[.][^.]+$", ""); // Gets the current file without the extension
File destFile = new File(destDir.getPath() + "\\" + file.getName()); // If a file of the same name exists in the dest folder
if (Files.exists(Paths.get(destFile.getPath()))) // Checks if there is a file with the same name in the folder
{
System.out.println("There is a duplicate.");
File[] destFiles = destDir.listFiles();
for (File destinationFile : destFiles) // Searches through the destination folder
{
if(destinationFile.getName().startsWith(fileNameWithOutExt)){ // Checks if the selected file has the same name as the file that's going to be moved.
y++; // Increments y by 1 to keep track of how many there are of the same/similar name
}
}
File newFile = new File(orgDir.getPath() + "\\" + fileNameWithOutExt + "." + y + selectedExtension); // Creates a new file with new name.
file.renameTo(newFile); // Renames to a unique name and moves the file to the destination folder
File destPath = new File(destDir.getPath() + "\\" + newFile.getName()); // Gets the destination path for the file
System.out.println(newFile.getCanonicalPath());
Files.copy(Paths.get(newFile.getCanonicalPath()), Paths.get(destPath.getPath())); // Renames the original file back to its original name
newFile.renameTo(new File(orgDir.getPath() + "\\" + fileNameWithOutExt + selectedExtension));
} else {
Files.copy(Paths.get(file.getPath()), Paths.get(destFile.getPath())); // Moves the file to the destination folder
}
}catch(Exception e){
e.printStackTrace();
}
} else{
startProcess(file, destDir);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am assuming your program is correct and this is purely memory issue. Increase the memory settings by running program with options -Xms 1024m -Xmx 1g, increase the values if necessary, be aware of your total available memory.
Will be nice to see a stack trace of exception to know for sure what caused the crash.
I need to copy a file from a working directory to an archiving directory, so I use the following code:
private void copyToArchive(Date today) {
try {
File source = new File("final.txt");
String msg = "getting source file " + source;
displayMessage(msg, good); // good points to a sound file
File destination = new File("archives\\final." + today + ".txt");
msg = "getting destination file " + destination;
displayMessage(msg, good);
FileUtils.copyFile(source, destination);
msg = "finished trying to copy file";
displayMessage(msg, good);
} catch (IOException ex) {
String message = "archiving failed";
displayMessage(message, bad);
Logger.getLogger(FileManagerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
The thing is, this works fine in the IDE, but in production it only succeeds as far as the declaration of "destination." In the IDE I get the "finished trying to copy file" notification (as well as the copied file in the subdirectory "archives"), but in production I get NEITHER the confirmation NOR the "archiving failed" notification from the IOException catch (and no copied file in the subdirectory).
Help?
(I run NetBeans 7.4 and the program runs on JDK version 1.7.0_55 (can't upgrade because another java program we run will not run on later java versions)).
I am not sure if it is your problem or not, but
File destination = new File("archives\\final." + today + ".txt");
should probably be
File destination = new File("archives","final." + today + ".txt");
for portability to file systems where \\ is not the directory separator.
You can try to use the Java Working Directory. It can be retrieved with:
String workingDir = System.getProperty("user.dir");
This will return your project's path.
So, on your case, your code would look like:
private void copyToArchive(Date today) {
try {
File source = new File("final.txt");
String msg = "getting source file " + source;
displayMessage(msg, good); // good points to a sound file
File destination = new File(workingDir + "archives\\final." + today + ".txt");
msg = "getting destination file " + destination;
displayMessage(msg, good);
FileUtils.copyFile(source, destination);
msg = "finished trying to copy file";
displayMessage(msg, good);
} catch (IOException ex) {
String message = "archiving failed";
displayMessage(message, bad);
Logger.getLogger(FileManagerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
IMPORTANT: maybe you would need as well writing file permissions. Here you have a very good example of how to read/set rights: http://www.mkyong.com/java/how-to-set-the-file-permission-in-java/
I'm trying to delete files but it isn't working or I'm missing something.
Here is a little test I'm doing:
private void deleteFromDir(String filename) {
String path = "./test/pacientes/" + filename + ".tds";
File f = new File(path);
System.out.println("Abs path " + f.getAbsolutePath());
System.out.println("Exist " + f.exists());
System.out.println("Filename " + f.getName());
System.out.println("Delete " + f.delete());
}
And the system prints:
Abs path C:\Users\XXXX\Documents\PAI\TSoft.\test\pacientes\John Smith.tds
Exist true
Filename John Smith.tds
Delete false
And of course isn't deleting the file, why? How can I make it work?
Perhaps, you do not have the permission to delete this file. You can use the Files.delete() method, which throws an IOException, in case something goes wrong, to see what the real problem is.
I am trying to use file.delete() but it does not delete file ? I tested it on linux it delete files but on windows it does not delete file why..?
code :
private File getFiletobeUpload(File foto) {
boolean errorRename = true;
File uploadFile = null;
File testFile = foto;
String subdirname = this.checkDir(foto);
if (testFile.canWrite()) {
uploadFile = new File(AppConstants.PHOTOPATH + "/" + subdirname + "/" + testFile.getName());
try {
FileInputStream origStream = new FileInputStream(testFile);
FileOutputStream outStream = new FileOutputStream(uploadFile);
origStream.getChannel().transferTo(0, testFile.length(), outStream.getChannel());
origStream.close();
origStream = null;
outStream.close();
outStream = null;
} catch (Exception e) {
this.errorString += "error while writing to orig dir";
logger.error(e);
}
errorRename = !testFile.delete();
if (errorRename) {
this.errorString += "error while deleting the file";
}
}
testFile = null;
return uploadFile;
}
your code seems a bit odd, you are checking "testFile" for write access but then actually reading from it (FileInputStream). Is the first try/catch block running without exception? Maybe you should check if the file even exists:
System.out.println("File exists: "+testFile.exists());
errorRename = !testFile.delete();
Also if you just want to rename a file, use:
file.renameTo(File dest)
A general suggestion: consider using the classes in the java.nio package to your file IO if you can (not sure which version of Java you're running with) because the error handling is improved and you should be able to find a more specific reason for the failure based on the type of exception thrown and the exception message.
As per API, the disk-drive specifier - "/" for the UNIX root directory, and "\\" for a Microsoft Windows UNC pathname.
so for windows:
uploadFile = new File(AppConstants.PHOTOPATH + "\\" + subdirname + "\\" + testFile.getName());
I am using icefaces to upload files to relative path in my web app (mywebapp/audio), then after the file is getting uploaded I rename it to save its extension as follows:
public static File changeExtToWav(FileInfo fileInfo,
StringBuffer originalFileName) {
log.debug("changeExtToWav");
int mid = fileInfo.getFile().getName().lastIndexOf(".");
String fileName = fileInfo.getFile().getName().substring(0, mid);
originalFileName.append(fileName);
log.debug("originalFileName: " + originalFileName);
String newFileName = fileName + "_" + new Date().getTime() + "."
+ "wav";
File newFile = new File(fileInfo.getFile().getParent() + "/"
+ newFileName);
log.debug("newFileName: " + newFile.getName());
fileInfo.getFile().renameTo(newFile);
return newFile;
}
after the file is getting uploaded, sometimes I want to delete it from UI button as follows:
try {
File fileToDelete = new File(filePath); // correct file path
log.debug("file exists: " + fileToDelete.exists()); // true
fileToDelete.delete();
} catch (Exception e) {
e.printStackTrace();
}
the file path is correct, and I get no exceptions, but the file is not deleted (I am using java 6 btw).
please advise how to fix this issue.
UPDATE: using the following useful method, I can get that the file is opened, any ideas how to close it ?
public String getReasonForFileDeletionFailureInPlainEnglish(File file) {
try {
if (!file.exists())
return "It doesn't exist in the first place.";
else if (file.isDirectory() && file.list().length > 0)
return "It's a directory and it's not empty.";
else
return "Somebody else has it open, we don't have write permissions, or somebody stole my disk.";
} catch (SecurityException e) {
return "We're sandboxed and don't have filesystem access.";
}
}
Well if the file is open, then there is two solutions :
You have a stream in your program open on this file. Note that afaik it's a problem on Windows, with Unix I can delete a File even if a stream is opened on it.
You have an other process using this file. So in this case you can't do anything from Java.
In the log it tells also that it can be a permission problem, are you sure you have enough privileges?
You can also use Files#delete(Path path) (jdk7) to have more details about the issue.