Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FilesAlreadyExistsException when using Files.copy() on File.createTempFile()

Tags:

java

file

jsf

I'm using JSF <h:inputFile> to upload images to the server.

<h:form enctype="multipart/form-data">
    <h:inputFile value="#{fileHandlerBean.file}"/>
    <h:commandButton action="#{fileHandlerBean.uploadImage()}"/>
</h:form>

I created a virtual host as /projectname/webapp/images. I can successfully create files into the folder.

private Part file;

public String uploadImage(){
    InputStream is = null;
    try {
        String extension = FilenameUtils.getExtension(file.getSubmittedFileName());
        File tempFile = File.createTempFile("picture-", "."+extension, new File("/projectname/webapp/images"));
        Logger.getLogger("FILE SIZE").warning(String.valueOf(file.getSize()));
        Logger.getLogger("FILE EXTENSION").warning(extension);
        is = file.getInputStream();
        Logger.getLogger("STREAM AVAILABLE SIZE").warning(String.valueOf(is.available()));
        Files.copy(is, tempFile.toPath());
    } catch (IOException ex) {
        Logger.getLogger(FileHandlerBean.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        if( is!= null){
            try {
                is.close();
            } catch (IOException ex) {
                Logger.getLogger(FileHandlerBean.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    return "success";
}

But all of them are empty and I get java.nio.file.FileAlreadyExistsException everytime.

java.nio.file.FileAlreadyExistsException: \projectname\webapp\images\picture-3433673623996534194.png
    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:81)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230)
    at java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:434)
    at java.nio.file.Files.newOutputStream(Files.java:216)
    at java.nio.file.Files.copy(Files.java:3016)
    at com.toolmanagement.backingbeans.FileHandlerBean.uploadImage(FileHandlerBean.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)

I use Logger to check the filesize, extension and streamsize, everything is fine.

How is this caused and how can I solve it?


Update: I added StandardCopyOption.REPLACE_EXISTING to Files.copy() and now it works, but it is still not solving the problem. I use createTempFile() to create unique, random filenames. Why would it say this file already exists?

like image 960
h2c Avatar asked May 15 '15 08:05

h2c


1 Answers

The File#createTempFile() indeed immediately creates an empty file. This is to guarantee that the filename is already reserved and available for use, hereby removing the (very small) risk that another thread coincidentally concurrently generates the same filename at the same moment.

You should indeed be using StandardCopyOption.REPLACE_EXISTING in Files#copy(). This flag was not necessary in old FileOutputStream approach as it already defaults to overwriting the file.

I gather that you got the createTempFile() example from this answer; it has in the meanwhile been updated to fix this oversight.

like image 94
BalusC Avatar answered Oct 04 '22 01:10

BalusC