首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在FTP服务器中存储文件内容时由于CopyStreamException而产生的SSLProtocolException

在FTP服务器中存储文件内容时由于CopyStreamException而产生的SSLProtocolException
EN

Stack Overflow用户
提问于 2022-07-21 11:31:49
回答 1查看 51关注 0票数 0

当我试图在FTP服务器中存储一个文件时,我面临一个问题。当试图将文件上载到FTP服务器时,将创建该文件,但其内容不会被复制。

上下文

我们使用以下配置来使用lftp访问FTP服务器。我无法更改此配置,也不知道为什么禁用验证证书时使用FTPS。

代码语言:javascript
复制
# FTPS_OPTIONS:
set ssl:verify-certificate/testhostname no;
set ftp:ssl-protect-data yes;
set ftp:passive-mode on;

我需要存储Java应用程序中的某些文件。我在使用。实现的代码如下所示:

代码语言:javascript
复制
@Autowired
public FtpService() {
  ftpsClient = new FTPSClient();
  ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
}

public void uploadFile(String ftpHost, File tempFile, String destination, String filename)
throws UploadException {

  ftpsClient.connect(ftpHost, 990);
  ftpsClient.execPBSZ(0);
  ftpsClient.execPROT("P");
  ftpsClient.enterLocalPassiveMode();
  ftpsClient.setKeepAlive(true);
  ftpsClient.setControlKeepAliveTimeout(3000);

  if(ftpsClient.login("user", "password")) {
    try (InputStream fileStream = new FileInputStream(tempFile)) {

      if (!ftpsClient.changeWorkingDirectory(destination)) {
        throwUploadException("Destination directory not available in FTP server");
      }

      boolean saved = ftpsClient.storeFile(filename, fileStream);
      // Following code is not executed since the exception is thrown in the previous line
      if (!saved) {
        throwUploadException("Unable to save file in FTP server");
      }
      log.info("Saved FTP file: {}/{}", destination, filename);
    }
    catch (UploadException | IOException e)
    {
      throwUploadException(e.getMessage());
    }
    finally
    {
      ftpsClient.disconnect();
      if (!tempFile.delete()) {
        log.warn("Unable to delete '{}' file", tempFile.getAbsolutePath());
      }
    }
  }
}

问题

我从一个FTPClient (非FTPSClient)开始,但这样我无法登录。

目前(FTPSClient),I可以

directory

  • create服务器
  • 更改

中的工作

  • 目录

I不能

  • storeFile:此方法引发以下异常,并在FTP服务器中创建文件,但这是空的。

org.apache.commons.net.io.CopyStreamException: IOException在复制时被捕获。原因: javax.net.ssl.SSLProtocolException:软件导致连接中断:套接字写入错误

  • listFiles()/listDirectories():执行此命令时,所获得的列表始终为空。日志记录的用户在整个FTP服务器

中拥有所有必需的权限。

下面是FTP的日志(请注意,我在括号之间将命令翻译成英文),对应于前面显示的代码,这会引发前面提到的异常:

代码语言:javascript
复制
er: testhostname:990
USER *******
331 Usuario testuser OK. Clave requerida ( = User testuser OK. Password required)
PASS *******
230 OK. El directorio restringido actual es / ( = OK. The current restricted directory is /)
CWD /test/upload
250 OK. El directorio actual es /test/upload ( = Ok. The current directory is /test/upload)
PASV
227 Entering Passive Mode (<numbers...>)
[Replacing PASV mode reply address <ip_address> with testhostname]
STOR dummyfile.txt
150 Conexi├│n de datos aceptada ( = Data connection accepted)

如果还有什么需要改进的地方,请告诉我。谢谢你的帮忙!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-22 14:24:31

在python连接到FTPS服务器时,我也遇到了类似的问题。错误是服务器要求数据通道会话与控制通道会话相同(重用会话)。解决方案是覆盖其中一种方法来做到这一点。

您可以测试扩展FTPClient.java并重写下一个方法:

代码语言:javascript
复制
@Override
protected void _prepareDataSocket_(final Socket socket) {
     if(preferences.getBoolean("ftp.tls.session.requirereuse")) {
         if(socket instanceof SSLSocket) {
             // Control socket is SSL
             final SSLSession session = ((SSLSocket) _socket_).getSession();
             if(session.isValid()) {
                 final SSLSessionContext context = session.getSessionContext();
                 context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));
                 try {
                     final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
                     sessionHostPortCache.setAccessible(true);
                     final Object cache = sessionHostPortCache.get(context);
                     final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                     putMethod.setAccessible(true);
                     Method getHostMethod;
                     try {
                         getHostMethod = socket.getClass().getMethod("getPeerHost");
                     }
                     catch(NoSuchMethodException e) {
                         // Running in IKVM
                         getHostMethod = socket.getClass().getDeclaredMethod("getHost");
                     }
                     getHostMethod.setAccessible(true);
                     Object peerHost = getHostMethod.invoke(socket);
                     putMethod.invoke(cache, String.format("%s:%s", peerHost, socket.getPort()).toLowerCase(Locale.ROOT), session);
                 }
                 catch(NoSuchFieldException e) {
                     // Not running in expected JRE
                     log.warn("No field sessionHostPortCache in SSLSessionContext", e);
                 }
                 catch(Exception e) {
                     // Not running in expected JRE
                     log.warn(e.getMessage());
                 }
             }
             else {
                 log.warn(String.format("SSL session %s for socket %s is not rejoinable", session, socket));
             }
         }
     }
 }

我在这里找到了这个https://stackoverflow.com/a/32404418/19599290解决方案:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73065400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档