如何修复使用 Apache Commons VFS 将文件上传到 SFTP 服务器时发生的错误

How to fix error occurring while uploading file to SFTP server using Apache Commons VFS

问题

我正在尝试使用 Apache Commons VFS 从远程桌面将文件上传到 SFTP 服务器。连接已正确建立,但是当我将文件复制到服务器时抛出异常:

[24.10. 11:43:27,672][DEBUG][saveDocumentToObject:536][CustomerService] >Connection string: sftp://uuu:xxx@ftp2.linde.grp/IASD/EXR3_U5/test14.txt<
[24.10. 11:43:27,672][DEBUG][saveDocumentToObject:536][CustomerService] >Copy local file to sftp server xxx<
[24.10. 11:43:27,672][ERROR][saveDocumentToObject:536][CustomerService] >Error while file saving on ftp server: Could not copy "file:///E:/SavedDocument/TemporarySavedDocs/test14.txt" to "sftp:////uuu:***@ftp2.linde.grp/IASD/EXR3_U5/test14.txt".Caused by: org.apache.commons.vfs2.FileSystemException: Could not create folder "sftp:////uuu:***@ftp2.linde.grp/IASD/".<
[24.10. 11:43:27,672][ERROR][saveDocumentToObject:536][CustomerService] >Stacktrace:[org.apache.commons.vfs2.provider.AbstractFileObject.copyFrom(AbstractFileObject.java:300), com.itac.linde.business.LindeDocumentBean.uploadFileToSFTPServer(LindeDocumentBean.java:149), com.itac.linde.business.LindeDocumentBean.saveDocumentToFolder(LindeDocumentBean.java:61), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method), sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081), org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153), com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4836), com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:836), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.itac.util.server.logging.ItacLoggingInterceptor.intercept(ItacLoggingInterceptor.java:210), sun.reflect.GeneratedMethodAccessor425.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64), org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52), sun.reflect.GeneratedMethodAccessor216.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163), com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140), sun.reflect.GeneratedMethodAccessor206.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:374), com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4808), com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4796), com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212), com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90), com.sun.proxy.$Proxy1666.saveDocumentToFolder(Unknown Source), com.itac.linde.server.LindeServiceBean.saveDocumentToFolder(LindeServiceBean.java:1834), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method), sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081), org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153), com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4836), com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:836), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.itac.persistence.interceptor.DaoInterceptorBase.aroundInvoke(DaoInterceptorBase.java:44), com.itac.persistence.interceptor.DaoInterceptor.prepareDaos(DaoInterceptor.java:20), sun.reflect.GeneratedMethodAccessor427.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.itac.util.server.logging.ItacLoggingInterceptor.intercept(ItacLoggingInterceptor.java:210), sun.reflect.GeneratedMethodAccessor425.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64), org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52), sun.reflect.GeneratedMethodAccessor216.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163), com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140), sun.reflect.GeneratedMethodAccessor206.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:374), com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4808), com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4796), com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212), com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90), com.sun.proxy.$Proxy1696.saveDocumentToFolder(Unknown Source), com.itac.linde.business.rest.LindeServiceRestBean.saveDocumentToObject(LindeServiceRestBean.java:3301), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method), sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081), org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153), com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4836), com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:836), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.itac.persistence.interceptor.DaoInterceptorBase.aroundInvoke(DaoInterceptorBase.java:44), com.itac.persistence.interceptor.DaoInterceptor.prepareDaos(DaoInterceptor.java:20), sun.reflect.GeneratedMethodAccessor427.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.itac.util.server.logging.ItacLoggingInterceptor.intercept(ItacLoggingInterceptor.java:210), sun.reflect.GeneratedMethodAccessor425.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64), org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52), sun.reflect.GeneratedMethodAccessor216.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608), com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163), com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140), sun.reflect.GeneratedMethodAccessor206.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:895), com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:835), com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:374), com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4808), com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4796), com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212), com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90), com.sun.proxy.$Proxy1689.saveDocumentToObject(Unknown Source), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method), sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), java.lang.reflect.Method.invoke(Method.java:498), org.glassfish.jersey.gf.ejb.internal.EjbComponentProvider.invoke(EjbComponentProvider.java:344), org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.run(AbstractJavaResourceMethodDispatcher.java:144), org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161), org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160), org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99), org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389), org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347), org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102), org.glassfish.jersey.server.ServerRuntime.run(ServerRuntime.java:326), org.glassfish.jersey.internal.Errors.call(Errors.java:271), org.glassfish.jersey.internal.Errors.call(Errors.java:267), org.glassfish.jersey.internal.Errors.process(Errors.java:315), org.glassfish.jersey.internal.Errors.process(Errors.java:297), org.glassfish.jersey.internal.Errors.process(Errors.java:267), org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317), org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305), org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154), org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473), org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427), org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388), org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341), org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228), org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1692), org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:258), org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160), org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:654), org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:593), com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99), org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159), org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:371), org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:238), com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:483), com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:180), org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206), org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180), org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235), org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119), org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284), org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201), org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133), org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112), org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77), org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539), org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112), org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117), org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:56), org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137), org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593), org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573), java.lang.Thread.run(Thread.java:748)]<
[24.10. 11:43:27,672][DEBUG][saveDocumentToObject:536][CustomerService] >Exit method LindeDocumentBean.saveDocumentToFolder Ret: (Integer): 571  returned in 15ms<
[24.10. 11:43:27,672][DEBUG][saveDocumentToObject:536][CustomerService] >Exit method LindeServiceBean.saveDocumentToFolder.<

代码

我根据代码编写了负责将文件上传到SFTP服务器的代码from this answer.这是我的代码:

  private int uploadFileToSFTPServer(String cylinderId, byte[] documentContent, URI locationURI) {
    StandardFileSystemManager manager = new StandardFileSystemManager();
    try {
      manager.addProvider("sftp", new DefaultLocalFileProvider());
      final String hostName = locationURI.toString();
      final String remoteFilePath = "IASD/EXR3_U5/" + cylinderId + ".txt";
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "Remote Path: " + remoteFilePath);
      InputStream inStream = new ByteArrayInputStream(documentContent);
      String localPath = "E:\SavedDocument\TemporarySavedDocs\" + cylinderId + ".txt";
      try {
        LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "Local path:" + localPath);
        Files.copy(inStream, Paths.get(localPath));
      } catch (Exception e) {
        LogHandler.log(LOGGER_NAME, LogLevel.WARN, "Exception while creating the file on local:" + e.getMessage());
      }
      final String loginFTP = lindeCustomServiceConfig.getValueForConfigKey(
          LindeCustomServiceConfigurationKeys.csLoginFTP, "admin");
      final String passwordFTP = lindeCustomServiceConfig.getValueForConfigKey(
          LindeCustomServiceConfigurationKeys.csPasswordFTP, "admin");
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "FTP user login:" + loginFTP);
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "FTP user password: " + passwordFTP);
      manager.init();
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "trying to create local file object ");
      FileObject localFile = manager.resolveFile(localPath);
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "trying to create remote file object ");
      String connectionString = createConnectionString(hostName, loginFTP, passwordFTP, remoteFilePath);
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "Connection string: " + connectionString);
      FileObject remoteFile = manager.resolveFile(connectionString, createDefaultOptions());
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "Copy local file to sftp server " + passwordFTP);
      remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
      LogHandler.log(LOGGER_NAME, LogLevel.DEBUG, "File upload success");
      return 202;
    } catch (IOException e) {
      LogHandler.log(LOGGER_NAME, LogLevel.ERROR, "Error while file saving on ftp server: " + e.getMessage() + "Caused by: " + e.getCause());
      LogHandler.log(LOGGER_NAME, LogLevel.ERROR, "Stacktrace:" + Arrays.toString(e.getStackTrace()));
      return 571;
    } catch (Exception e) {
      LogHandler.log(LOGGER_NAME, LogLevel.ERROR, "Problem with store file on ftp server:" + e.getMessage());
      return 572;
    } finally {
      manager.close();
    }
  }

  private String createConnectionString(String hostName, String username, String password, String remoteFilePath) {
    return "sftp://" + username + ":" + password + "@" + hostName + "/" + remoteFilePath;
  }

  private FileSystemOptions createDefaultOptions() throws FileSystemException {
    // Create SFTP options
    FileSystemOptions opts = new FileSystemOptions();
    // SSH Key checking
    SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
    // Root directory set to user home
    SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, false);
    // Timeout is count by Milliseconds
    SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 30000);
    return opts;
  }

如能提供修复此错误的建议,我将不胜感激。

我对 VFS 经验不多,但这看起来很可疑:

manager.addProvider("sftp", new DefaultLocalFileProvider());

我猜应该是:

manager.addProvider("sftp", new SftpFileProvider());