2016-04-08 3 views
1

Я использую JSF 2.2 и Primefaces 5.3. Я хотел бы сохранить загруженный файл на диске. Ниже вы можете увидеть, как я пытаюсь это сделать. Когда я нажимаю кнопку Send я получаю java.nio.file.NoSuchFileException исключение (в конце моего поста я поставил полный StackTrace):uploadFile.getInputstream() throws java.nio.file.NoSuchFileException

ERROR [STDERR] (по умолчанию задача-24) java.nio.file.NoSuchFileException: [PATH] \ Wildfly_10 \ WILDFLY_HOME \ автономный \ TMP \ MasterProject.war \ undertow1357918758070690245upload

Когда я проследить StackTrace, я вижу, что исключение вызвано этой линии (я так думаю):

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

Странно для меня. Я могу получить имя загруженного файла (по uploadFile.getFileName()), но я не могу получить размер файла (по uploadFile.getSize()), и я не могу получить InputStream (по uploadFile.getInputstream()). В обоих случаях я получаю исключение NoSuchFileException.

Дополнительная информация: Я должен загружать большие файлы (то есть 200 МБ или более). Конечно, я получаю такое же исключение, когда я загружаю небольшой файл.

У вас есть идея, почему у меня есть это исключение и как я могу исправить эту проблему?

Это часть страницы, где я могу загрузить файл:

<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, который представляет собой контроллер для указанной выше странице:

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

Это самый полный 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) 

Обновление:

Я заметил что-то новое. Если переместить содержимое методы 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), поэтому необходимо сохранить файл в send().

Я также заметил, что когда я использую простой режим компонента <p:fileUpload> (измененная форма ниже), все работает (т. Е. Файл сохраняется, когда пользователь нажимает кнопку). Мне нужно было создать геттер и сеттер для объекта в компоненте DataController для использования #{dataController.uploadFile}. Мне пришлось добавить атрибут enctype="multipart/form-data" к компоненту <h:form> (без этого атрибута он не работает).

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

Проблема этого решения заключается в: Мне нужен расширенный режим <p:fileUpload> компонента.

Я не понимаю, почему я не могу получить доступ к загруженному файлу в методе send(), когда я использую расширенный режим. Я использую область @ViewScoped, чтобы она работала.

ответ

2

uploadFile.getInputstream() бросает java.nio.file.NoSuchFileException

Ваша конкретная проблема вызвана тем, что вы пытаетесь прочитать загруженный файл, который был закачанный в предыдущем запросе. Немного приличный контейнер очистит все временные данные, связанные с HTTP-запросом, когда HTTP-запрос завершится. Это, по-видимому, также охватывает нечитаемые загруженные файлы в случае WildFly (не уверен, как ведут себя другие).

Ваш лучший выбор напрямую сохраняет их в любом случае, если необходимо, в некотором временном месте. Затем, в конечном действии, переместите/переименуйте их в нужное постоянное место/имя. Чтобы очистить «забытые» файлы для случая, конечный пользователь никогда не вызывает метод окончательного действия после того, как вы загрузили кучу файлов, лучше всего отслеживать все эти File s в фазе с сессией и выполнять file.delete() в @PreDestroy аннотированных метод. Конкретный пример можно найти здесь: How to handle and delete "forgotten" uploaded files?

Если форма загружаемом вид области действия, и вы используете OmniFaces, то вы можете также использовать в качестве альтернативы OmniFaces CDI @ViewScoped которого @PreDestroy уже будет работать, когда пользователь выгружает страницу по навигации или закрытия вкладки/окна.

+0

Большое спасибо за вашу помощь! Я развернул ваше [первое] (http://stackoverflow.com/q/27833140) решение для моего проекта, и он отлично работает. – Robert

+0

Добро пожаловать. – BalusC

1

Реализация выбранного ответа

Я забыл добавить реализацию выбранного ответа, поэтому я делаю это сейчас. Основываясь на одном из раствора заданной @BalusC:

  1. Я добавил UserFileManager боб (ниже код), который управляет неподтвержденные файлы и удаляет их, если сеанс истек.
  2. Я ввел UserFileManager в фасоль DataController.
  3. Я переместил try catch из send() метод в метод handleFileUpload(), поэтому на момент сохранения файла на диске, когда пользователь нажимает кнопку Upload.
  4. После сохранения файла во временной папке - я вызвал userFileManager.addUnconfirmedUploadedFile(file) в методе handleFileUpload(). Теперь мы уверены, что файл будет удален (когда истечет срок действия сеанса), если пользователь не нажимает кнопку Send.
  5. В конце я позвонил userFileManager.confirmUploadedFile(file) по телефону send(). Теперь мы уверены, что пользователь хочет сохранить файл на диске, чтобы мы удалили этот файл из списка неподтвержденных файлов.

Примечание: Загруженные файлы сохраняются в папке для записи /standalone/data/upload WildFly сервера или в /standalone/data папку, если что-то пошло не так во время создания папки upload.

Это самый модифицированный DataController боб:

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

Это самый UserFileManager боб, который был создан @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; 
} 
+1

'Paths.get (« F:/Wildfly/Files »)' - знаете ли вы о 'System.getProperty (« jboss.server.data.dir »)'? Лучше его использовать. Он представляет собой абсолютный путь к записи JBoss, доступной для записи в папку '/ standalone/data', без необходимости жесткого кодирования. Вы можете просто создать папку '/ Files' в ней через' File # mkdirs() ', если она не существует. См. Также a.o. http://stackoverflow.com/q/18664579 – BalusC

+0

Спасибо за ваш совет. Я только что развернул это, и я обновил свой ответ. Как вы предположили, я использовал 'File # mkdirs()', чтобы создать папку 'upload' в папке'/standalone/data' сервера WildFly для моих загруженных файлов, поэтому, наконец, я использовал 'Paths.get (System. GetProperty ("jboss.server.data.dir"), "загрузить") '. – Robert

Смежные вопросы