如何使用相对于应用程序的文件路径在服务器上创建文件?

How to create file on server with file path relative to application?

在我的 Vaadin spring 启动应用程序中,我需要将文件上传到服务器并保存在那里。

将文件本地上传到我的桌面工作正常, 但是我想把应用程序部署到服务器上,所以我想把上传的文件保存在相对于我的应用程序基本路径的目录中。

我创建了一个名为 "input_files" 的文件夹作为根应用程序文件夹 (applicationName -> input_files) 的直接子文件夹。上传文件时,文件的内容应该写入此 "input_files" 文件夹内的新创建文件。

代码:

class FileReceiver implements Upload.Receiver, Upload.SucceededListener {
  private File file;

  public OutputStream receiveUpload(String filename, String mimeType) {
    String basePath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();                
    FileOutputStream fileOutputStream;

    try {
      //this line would work:
      //file = new File("/Users/username/Desktop/input_files/" + filename);          

      //this line does not work:
      file = new File(basePath + "/input_files/" + filename);


      fileOutputStream = new FileOutputStream(file);
      labelFilename.setCaption(filename);
    }
    catch (final java.io.FileNotFoundException e) {
      new Notification("Could not open file", e.getMessage(), Notification.Type.ERROR_MESSAGE).show(Page.getCurrent());
      return null;
    }
    return fileOutputStream;
  }

  public void uploadSucceeded(Upload.SucceededEvent event) {

  }
};

重要的代码行是这样的:

file = new File(basePathOfApplication + "/input_files/" + filename);

这条线不起作用。 input_files 文件夹中没有创建文件。

*********************************更新************ **********************

屏幕上显示的错误信息:

控制台中的错误消息:

com.vaadin.server.UploadException: Upload failed
    at com.vaadin.server.communication.FileUploadHandler.streamToReceiver(FileUploadHandler.java:631) [vaadin-server-8.1.0.jar:8.1.0]
    at com.vaadin.server.communication.FileUploadHandler.handleFileUploadValidationAndData(FileUploadHandler.java:460) [vaadin-server-8.1.0.jar:8.1.0]
    at com.vaadin.server.communication.FileUploadHandler.doHandleSimpleMultipartFileUpload(FileUploadHandler.java:413) [vaadin-server-8.1.0.jar:8.1.0]
    at com.vaadin.server.communication.FileUploadHandler.handleRequest(FileUploadHandler.java:290) [vaadin-server-8.1.0.jar:8.1.0]
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1568) [vaadin-server-8.1.0.jar:8.1.0]
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:381) [vaadin-server-8.1.0.jar:8.1.0]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
Caused by: com.vaadin.server.NoOutputStreamException: null
    at com.vaadin.server.communication.FileUploadHandler.streamToReceiver(FileUploadHandler.java:559) [vaadin-server-8.1.0.jar:8.1.0]
    ... 43 common frames omitted

确保您的应用程序可以在目录 /private/var/... 中创建文件。很可能,它不能。我不太了解Vaadin,但文件夹本身可能是一个"read-only" / "temporary" 目录,用于存储解压后的类 和应用程序所需的数据。此目录可能不用于存储任何上传和动态内容。

documentation 状态:

Returns the context base directory. Typically an application is deployed in a such way that is has an application directory. For web applications this directory is the root directory of the web applications. In some cases applications might not have an application directory (for example web applications running inside a war).

因此,它甚至可能 null,这也会破坏您的代码。

恕我直言,最好使用另一个可以通过应用程序配置指定的专用上传目录。或者使用众所周知的位置,例如 /tmp.

此外,确保先使用 file.getParentFile().mkdirs() 创建父目录。

您不应该在 Vaadin 服务中保存文件,根据 Vaadin forum

您应该将文件保存在 app.getContext().getBaseDirectory()

  • 注意:应用所在的位置 com.vaadin.Application

你可以检查一个 Sample 也检查 属性 以防它不起作用:

 // cannot access example directory, possible security issue with
// Application Server or Servlet Container
// Try to read sample directory from web.xml parameter
if (application.getProperty("sampleDirectory") != null) {
                file = new File(application.getProperty("sampleDirectory"));
                if ((file != null) && (file.canRead())
                        && (file.getAbsolutePath() != null)) {
                    // Success using property
                    return file;
                }

您的文件夹没有权限,请尝试授予它完全权限,例如 /tmp 拥有

drwxrwxrwt  15 root root 4.0K Nov  4 20:23 tmp

使用sudo chmod 777 /opt/myapp/input_files/

之后尝试执行您的代码。

注意:我使用过/opt/use 也可以使用任何其他文件夹,但请记住授予它权限。