【问题标题】:uploadFile.getInputstream() throws java.nio.file.NoSuchFileExceptionuploadFile.getInputstream() 抛出 java.nio.file.NoSuchFileException
【发布时间】:2016-07-29 12:35:21
【问题描述】:

我使用 JSF 2.2 和 Primefaces 5.3。我想将上传的文件保存在磁盘上。下面你可以看到我是如何尝试做到这一点的。当我按下Send 按钮时,我得到一个java.nio.file.NoSuchFileException 异常(在我的帖子末尾我还放了一个完整的堆栈跟踪):

错误 [stderr](默认任务 24)java.nio.file.NoSuchFileException: [PATH]\Wildfly_10\WILDFLY_HOME\standalone\tmp\MasterProject.war\undertow1357918758070690245upload

当我跟踪堆栈跟踪时,我看到异常是由这一行引起的(我认为是这样):

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

这对我来说很奇怪。我可以获取上传文件的名称(uploadFile.getFileName()),但我无法获取文件的大小(uploadFile.getSize()),也无法获取InputStreamuploadFile.getInputstream())。在这两种情况下,我都会收到 NoSuchFileException 异常。

附加信息:我必须上传大文件(即 200 MB 或更多)。当然,我上传小文件时也会遇到同样的异常。

您知道为什么会出现此异常以及如何解决此问题吗?

这是我上传文件的页面的一部分:

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

这是 CDI bean,它是上述页面的控制器:

@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;
}

这是完整的堆栈跟踪:

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)

更新:

我发现了一些新东西。如果我将send() 方法的内容移动到handleFileUpload() 方法(下面的代码) - 文件将保存在磁盘上:

@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;
}

但是如果用户按下Send 按钮,我想将上传的文件保存在磁盘上,而不是更早(即当用户按下Upload 按钮时),所以有必要将文件保存在@ 987654337@ 方法。

我还注意到,当我使用&lt;p:fileUpload&gt; 组件的简单模式(下面的修改形式)时,一切正常(即当用户按下按钮时文件被保存)。我必须为DataController bean 中的uploadFile 对象创建getter 和setter 才能使用#{dataController.uploadFile}。我也必须将enctype="multipart/form-data" 属性添加到&lt;h:form&gt; 组件中(没有此属性将不起作用)。

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

这个解决方案的问题是:我需要&lt;p:fileUpload&gt;组件的高级模式。

我不明白为什么我使用高级模式时无法访问send()方法中上传的文件。我使用@ViewScoped 范围,所以它应该可以工作。

【问题讨论】:

    标签: jsf file-upload primefaces wildfly


    【解决方案1】:

    uploadFile.getInputstream() 抛出 java.nio.file.NoSuchFileException

    您的具体问题是由于您试图读取在先前请求中上传的上传文件而引起的。当 HTTP 请求完成时,一个像样的容器会清理与 HTTP 请求相关的所有临时数据。这显然也涵盖了 WildFly 的未读取上传文件(虽然不确定其他人的行为)。

    最好的办法是直接保存它们,如有必要,在某个临时位置。然后,在最终操作方法中,将它们移动/重命名为所需的永久位置/名称。为了清理“被遗忘”的文件,最终用户在上传一堆文件后从不调用最终操作方法,最好的办法是在会话范围的 bean 中跟踪所有这些 Files 并执行 @987654325 @ 在@PreDestroy 注释方法中。一个具体的例子可以在这里找到:How to handle and delete "forgotten" uploaded files?

    如果上传表单是视图范围的,并且您使用的是 OmniFaces,那么您也可以使用 OmniFaces CDI @ViewScoped,其 @PreDestroy 将在用户通过导航或关闭选项卡/窗口。

    【讨论】:

    • 非常感谢您的帮助!我在我的项目中部署了您的 first 解决方案,它运行良好。
    【解决方案2】:

    所选答案的实现

    我忘记添加所选答案的实现,所以我现在就做。基于@BalusC 给出的解决方案之一:

    1. 我添加了UserFileManager bean(下面的代码),它管理未确认的文件并在会话过期时将其删除。
    2. 我将UserFileManager 注入DataController bean。
    3. 我将try catchsend() 方法移动到handleFileUpload() 方法,因此当用户按下Upload 按钮时,文件将保存在磁盘上。
    4. 将文件保存到临时文件夹后 - 我在handleFileUpload() 方法中调用了userFileManager.addUnconfirmedUploadedFile(file)。现在我们确定如果用户不按下Send 按钮,文件将被删除(当会话到期时)。
    5. 最后我在send()方法中调用了userFileManager.confirmUploadedFile(file)。现在我们确定用户希望将该文件保留在磁盘上,因此我们从未确认文件列表中删除该文件。

    注意:如果在创建 upload 文件夹期间出现问题,您上传的文件将存储在 WildFly 服务器的可写 /standalone/data/upload 文件夹或 /standalone/data 文件夹中。

    这是修改后的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;
    }
    

    这是 @BalusC here 创建的 UserFileManager bean:

    @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;
    }
    

    【讨论】:

    • Paths.get("F:/Wildfly/Files") -- 你知道System.getProperty("jboss.server.data.dir")吗?更好地使用它。它表示 JBoss 服务器的可写/standalone/data 文件夹的绝对路径,无需对其进行硬编码。如果不存在,您可以通过File#mkdirs() 在其中创建/Files 文件夹。另见 a.o. stackoverflow.com/q/18664579
    • 感谢您的建议。我刚刚部署了这个,我已经更新了我的答案。正如你所建议的,我使用File#mkdirs() 在WildFly 服务器的可写/standalone/data 文件夹中为我上传的文件创建upload 文件夹,所以最后我使用了Paths.get(System.getProperty("jboss.server.data.dir"),"upload")
    猜你喜欢
    • 2021-11-18
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 2014-02-17
    • 2022-01-26
    • 1970-01-01
    • 2020-04-10
    相关资源
    最近更新 更多