Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

uploadFile.getInputstream() throws java.nio.file.NoSuchFileException

I use a JSF 2.2 and a Primefaces 5.3. I'd like to save a uploaded file on a disk. Below you can see how I try to do this. When I push a Send button I get a java.nio.file.NoSuchFileException exception (at the end of my post I also put a full stacktrace):

ERROR [stderr] (default task-24) java.nio.file.NoSuchFileException: [PATH]\Wildfly_10\WILDFLY_HOME\standalone\tmp\MasterProject.war\undertow1357918758070690245upload

When I trace the stacktrace, I see that the exception is caused by this line (I think so):

try(InputStream input = uploadFile.getInputstream()){

It's strange for me. I can get the name of the uploaded file (by uploadFile.getFileName()) but I can't get the size of the file (by uploadFile.getSize()) and I can't get the InputStream (by uploadFile.getInputstream()). In both cases I get the NoSuchFileException exception.

Additional information: I've to upload the large files (i.e. 200 MB or more). Of course I get the same exception when I upload the small file.

Have you got any idea why have I got this exception and how can I fix this issue?

This's part of the page where I upload the file:

<h:form>
    <p:growl id="messages" showDetail="true" />
    <p:panelGrid id="panel" columns="2" styleClass="ui-noborder" columnClasses="rightalign,leftalign">

        <p:outputLabel for="file" value="File:" />
        <p:fileUpload id="file" fileLimit="1"
                    fileUploadListener="#{dataController.handleFileUpload}" 
                    mode="advanced" dragDropSupport="true" sizeLimit="1000000000" 
                    uploadLabel="Upload" cancelLabel="Delete" allowTypes="/(\.|\/)(csv|binetflow)$/" />                                             
        <p:commandButton id="buttonSend" value="Send" 
                        action="#{dataController.send()}" update="messages"/>                       

    </p:panelGrid>                                              
</h:form>

This's the CDI bean which is the controller for the above page:

@Named
@ViewScoped
public class DataController implements Serializable {

    private static final long serialVersionUID = 1383572529241805730L;

    public void handleFileUpload(FileUploadEvent event){

        uploadFile=event.getFile(); 

        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful", event.getFile().getFileName() + " is uploaded"));
    }

    public void send(){

        try(InputStream input = uploadFile.getInputstream()){

            Path folder=Paths.get("F:/Files");
            String filename = FilenameUtils.getBaseName(uploadFile.getFileName()); 
            String extension = FilenameUtils.getExtension(uploadFile.getFileName());
            Path file = Files.createTempFile(folder, filename + "-", "." + extension);
            Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);

            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful", "Uploaded file successfully saved in " + file));          

        } catch (IOException e1) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR", null));
            e1.printStackTrace();
        }   
    }

    private UploadedFile uploadFile;
}

This's the full stacktrace:

10:40:45,822 ERROR [stderr] (default task-24) java.nio.file.NoSuchFileException: [PATH]\Wildfly_10\WILDFLY_HOME\standalone\tmp\MasterProject.war\undertow1357918758070690245upload

10:40:45,823 ERROR [stderr] (default task-24)   at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)

10:40:45,823 ERROR [stderr] (default task-24)   at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)

10:40:45,823 ERROR [stderr] (default task-24)   at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)

10:40:45,823 ERROR [stderr] (default task-24)   at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230)

10:40:45,823 ERROR [stderr] (default task-24)   at java.nio.file.Files.newByteChannel(Files.java:361)

10:40:45,824 ERROR [stderr] (default task-24)   at java.nio.file.Files.newByteChannel(Files.java:407)

10:40:45,824 ERROR [stderr] (default task-24)   at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)

10:40:45,824 ERROR [stderr] (default task-24)   at java.nio.file.Files.newInputStream(Files.java:152)

10:40:45,824 ERROR [stderr] (default task-24)   at io.undertow.servlet.spec.PartImpl.getInputStream(PartImpl.java:63)

10:40:45,824 ERROR [stderr] (default task-24)   at org.primefaces.model.NativeUploadedFile.getInputstream(NativeUploadedFile.java:45)

10:40:45,824 ERROR [stderr] (default task-24)   at com.system.controller.DataController.send(DataController.java:163)

10:40:45,824 ERROR [stderr] (default task-24)   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

10:40:45,825 ERROR [stderr] (default task-24)   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

10:40:45,825 ERROR [stderr] (default task-24)   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

10:40:45,825 ERROR [stderr] (default task-24)   at java.lang.reflect.Method.invoke(Method.java:498)

10:40:45,825 ERROR [stderr] (default task-24)   at javax.el.ELUtil.invokeMethod(ELUtil.java:308)

10:40:45,825 ERROR [stderr] (default task-24)   at javax.el.BeanELResolver.invoke(BeanELResolver.java:415)

10:40:45,825 ERROR [stderr] (default task-24)   at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:256)

10:40:45,825 ERROR [stderr] (default task-24)   at com.sun.el.parser.AstValue.invoke(AstValue.java:285)

10:40:45,825 ERROR [stderr] (default task-24)   at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)

10:40:45,826 ERROR [stderr] (default task-24)   at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)

10:40:45,826 ERROR [stderr] (default task-24)   at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)

10:40:45,826 ERROR [stderr] (default task-24)   at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)

10:40:45,826 ERROR [stderr] (default task-24)   at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)

10:40:45,826 ERROR [stderr] (default task-24)   at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)

10:40:45,826 ERROR [stderr] (default task-24)   at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)

10:40:45,826 ERROR [stderr] (default task-24)   at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)

10:40:45,827 ERROR [stderr] (default task-24)   at javax.faces.component.UICommand.broadcast(UICommand.java:315)

10:40:45,827 ERROR [stderr] (default task-24)   at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)

10:40:45,827 ERROR [stderr] (default task-24)   at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)

10:40:45,827 ERROR [stderr] (default task-24)   at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)

10:40:45,827 ERROR [stderr] (default task-24)   at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)

10:40:45,827 ERROR [stderr] (default task-24)   at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)

10:40:45,828 ERROR [stderr] (default task-24)   at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)

10:40:45,828 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)

10:40:45,828 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)

10:40:45,828 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)

10:40:45,829 ERROR [stderr] (default task-24)   at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)

10:40:45,829 ERROR [stderr] (default task-24)   at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)

10:40:45,829 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)

10:40:45,829 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)

10:40:45,829 ERROR [stderr] (default task-24)   at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)

10:40:45,830 ERROR [stderr] (default task-24)   at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)

10:40:45,830 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)

10:40:45,830 ERROR [stderr] (default task-24)   at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)

10:40:45,830 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)

10:40:45,831 ERROR [stderr] (default task-24)   at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)

10:40:45,831 ERROR [stderr] (default task-24)   at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)

10:40:45,831 ERROR [stderr] (default task-24)   at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)

10:40:45,831 ERROR [stderr] (default task-24)   at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)

10:40:45,831 ERROR [stderr] (default task-24)   at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)

10:40:45,832 ERROR [stderr] (default task-24)   at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)

10:40:45,832 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)

10:40:45,832 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)

10:40:45,832 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)

10:40:45,833 ERROR [stderr] (default task-24)   at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)

10:40:45,833 ERROR [stderr] (default task-24)   at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)

10:40:45,833 ERROR [stderr] (default task-24)   at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)

10:40:45,833 ERROR [stderr] (default task-24)   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

10:40:45,833 ERROR [stderr] (default task-24)   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

10:40:45,834 ERROR [stderr] (default task-24)   at java.lang.Thread.run(Thread.java:745)

Update:

I noticed something new. If I move the contents of the send() method to the handleFileUpload() method (the code below) - the file is saved on the disk:

@Named
@ViewScoped
public class DataController implements Serializable {

    private static final long serialVersionUID = 1383572529241805730L;

    public void handleFileUpload(FileUploadEvent event){

        uploadFile=event.getFile(); 

        try(InputStream input = uploadFile.getInputstream()){

            Path folder=Paths.get("F:/Files");
            String filename = FilenameUtils.getBaseName(uploadFile.getFileName()); 
            String extension = FilenameUtils.getExtension(uploadFile.getFileName());
            Path file = Files.createTempFile(folder, filename + "-", "." + extension);
            Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);

            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful", "Uploaded file successfully saved in " + file));          

        } catch (IOException e1) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR", null));
            e1.printStackTrace();
        }

        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful", event.getFile().getFileName() + " is uploaded"));
    }

    public void send(){

    }

    private UploadedFile uploadFile;
}

But I'd like to save the uploaded file on the disk if the user push the Send button, not earlier (i.e. not when the user push the Upload button) so it's necessary to save the file in send() method.

I also noticed that when I use a simple mode of the <p:fileUpload> component (the modified form below), everything work (i.e. the file is saved when the user push the button). I had to create getter and setter for the uploadFile object in the DataController bean to use #{dataController.uploadFile}. I had to add the enctype="multipart/form-data" attribute to the <h:form> component either (without this attribute it isn't work).

<h:form enctype="multipart/form-data">
    <p:growl id="messages" showDetail="true" />
    <p:panelGrid id="panel" columns="2" styleClass="ui-noborder" columnClasses="rightalign,leftalign">

        <p:outputLabel for="file" value="File:" />
        <p:fileUpload id="file" value="#{dataController.uploadFile}" mode="simple" skinSimple="true" sizeLimit="1000000000" allowTypes="/(\.|\/)(csv|binetflow)$/"/>
        <p:commandButton value="Submit" ajax="false" actionListener="#{dataController.send()}" disabled="false" />                                                                                                                                          

    </p:panelGrid>                                              
</h:form>

The problem of this solution is: I need the advanced mode of the <p:fileUpload> component.

I don't understand why I can't access to the uploaded file in the send() method when I use the advanced mode. I use the @ViewScoped scope so it should work.

like image 932
Robert Avatar asked Jan 06 '23 07:01

Robert


2 Answers

uploadFile.getInputstream() throws java.nio.file.NoSuchFileException

Your concrete problem is caused because you're attempting to read an uploaded file which was uploaded in a previous request. A bit decent container will clean up all temporary data associated with a HTTP request when the HTTP request finishes. This apparently also covers non-read uploaded files in case of WildFly (not sure how others behave though).

Your best bet is directly save them anyway, if necessary in some temporary location. Then, in the final action method, move/rename them to the desired permanent location/name. In order to cleanup "forgotten" files for the case the enduser never invokes the final action method after having uploaded a bunch of files, your best bet is to keep track of all those Files in a session scoped bean and perform file.delete() in @PreDestroy annotated method. A concrete example can be found here: How to handle and delete "forgotten" uploaded files?

If the upload form is view scoped, and you're using OmniFaces, then you can alternatively also use OmniFaces CDI @ViewScoped whose @PreDestroy will already run when the user unloads the page by a navigation or close of tab/window.

like image 74
BalusC Avatar answered Apr 26 '23 14:04

BalusC


The implementation of the selected answer

I forgot to add the implementation of the selected answer so I'm doing it now. Based on one of the solution given by @BalusC:

  1. I added the UserFileManager bean (the code below) which manages the unconfirmed files and deletes them if the session is expired.
  2. I injected the UserFileManager to the DataController bean.
  3. I moved try catch from send() method to the handleFileUpload() method, so at the moment the file is saved on the disk when the user pushes the Upload button.
  4. After saving the file in the temporary folder - I called userFileManager.addUnconfirmedUploadedFile(file) in handleFileUpload() method. Now we're sure that the file will be deleted (when the session expires) if the user doesn't push the Send button.
  5. At the end I called userFileManager.confirmUploadedFile(file) in send() method. Now we're sure that the user wants to keep the file on the disk so we delete this file from the list of the unconfirmed files.

Note: Your uploaded files are stored in WildFly server's writable /standalone/data/upload folder or in /standalone/data folder if something went wrong during the creation of the upload folder.

This's the modified DataController bean:

@Named
@ViewScoped
public class DataController implements Serializable {

    private static final long serialVersionUID = 1383572529241805730L;

    public void handleFileUpload(FileUploadEvent event){

        uploadFile=event.getFile();    

        try(InputStream input = uploadFile.getInputstream()){

            Path folder=Paths.get(System.getProperty("jboss.server.data.dir"),"upload");

            if(!folder.toFile().exists()){
                if(!folder.toFile().mkdirs()){
                    folder=Paths.get(System.getProperty("jboss.server.data.dir"));
                }
            }

            String filename = FilenameUtils.getBaseName(uploadFile.getFileName()); 
            String extension = FilenameUtils.getExtension(uploadFile.getFileName());
            Path filePath = Files.createTempFile(folder, filename + "-", "." + extension);
            Files.copy(input, filePath, StandardCopyOption.REPLACE_EXISTING);

            userFileManager.addUnconfirmedUploadedFile(filePath.toFile());

            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful", event.getFile().getFileName() + " is uploaded"));

        } catch (IOException e1) {

            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR I/O", "Code of the error: DC1"));
            e1.printStackTrace();
        }
    }

    public void send(){

        userFileManager.confirmUploadedFile(filePath.toFile());

        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "The data has been added.", ""));
    }

     @Inject
    private UserFileManager userFileManager;
    private UploadedFile uploadFile;
}

This's the UserFileManager bean which was created by @BalusC here:

@SessionScoped
public class UserFileManager implements Serializable {

    private static final long serialVersionUID = -5410871255899363212L;

    /**
     * Initialization of list.
     */
    @PostConstruct
    public void init(){
        unconfirmedUploadedFiles = new ArrayList<>();
    }

    /**
     * Adding the unconfirmed file to the list.
     * @param unconfirmedUploadedFile unconfirmed file.
     */
    public void addUnconfirmedUploadedFile(File unconfirmedUploadedFile) {
        unconfirmedUploadedFiles.add(unconfirmedUploadedFile);
    }

    /**
     * Deleting the confirmed file from the list.
     * @param confirmedUploadedFile confirmed file. 
     */
    public void confirmUploadedFile(File confirmedUploadedFile) {
        unconfirmedUploadedFiles.remove(confirmedUploadedFile);
    }

    /**
     * Deleting unconfirmed files from the disk if the session is expired.
     */
    @PreDestroy
    public void destroy() {
        for (File unconfirmedUploadedFile : unconfirmedUploadedFiles) {
            unconfirmedUploadedFile.delete();
        }
    }   

    //The list which stores the unconfirmed files.
    private List<File> unconfirmedUploadedFiles;
}
like image 27
Robert Avatar answered Apr 26 '23 13:04

Robert