我在我的
Android应用程序中使用
Apache Commons FTP library
我通过FTPS建立连接,虽然它与服务器完美连接,但在传输文件时遇到问题.
出于安全原因,订购应用程序的客户端在使用PROT P时请求在数据连接上恢复TLS会话.
因此,我在服务器上启用了此选项:
正如我所说,我可以连接到服务器,但不能传输文件.
如果我取消激活“使用PROT P时数据连接上所需的TLS会话恢复”框,则传输正常.
我正在寻找一种使用库进行文件传输的方法,但是没有成功,但我知道必须有办法.
我给你相关代码的一部分:
TransferImagenesFTP.ftpClient = new FTPSClient(); TransferImagenesFTP.ftpClient.connect(InetAddress.getByName("XXX_XXX_XX_X"),26); TransferImagenesFTP.ftpClient.enterLocalPassiveMode(); TransferImagenesFTP.ftpClient.setBufferSize(1024000); TransferImagenesFTP.ftpClient.login("xxxxxx","zzzzzz"); TransferImagenesFTP.ftpClient.execPROT("P"); TransferImagenesFTP.ftpClient.type(FTP.BINARY_FILE_TYPE);
我感谢任何帮助,谢谢.
解决方法
您可以尝试以下代码,我希望它也适用于您的情况.
该代码使用Apache Commons vsf2通过安全ftp连接(SFTP)上传文件
try { String filepath = "<FILE PATH>"; String serverAddress = "<FTP SERVER ADDRESS>"; String userId = "<FTP USER ID>"; String password = "<FTP PASSWORD>"; String remoteDirectory = "<FTP DIRECTORY TO UPLOAD TO>"; String keyPath = "<PATH TO YOUR KEY>"; String passPhrase = "<PASSWORD FOR YOUR KEY>"; File file = new File(filepath); if (!file.exists()) throw new RuntimeException("Error. File not found"); //Initializes the file manager StandardFileSystemManager manager = new StandardFileSystemManager(); manager.init(); //Setup our SFTP configuration FileSystemOptions opts = new FileSystemOptions(); SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts,"no"); SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts,true); SftpFileSystemConfigBuilder.getInstance().setTimeout(opts,10000); // Create local file object FileObject localFile = manager.resolveFile(file.getAbsolutePath()); // Create remote file object FileObject remoteFile = manager.resolveFile(createConnectionString(serverAddress,userId,password,keyPath,passPhrase,fileToFTP),createDefaultOptions(keyPath,passPhrase)); // Copy local file to sftp server remoteFile.copyFrom(localFile,Selectors.SELECT_SELF); System.out.println("File upload successful"); } catch (Exception ex) { ex.printStackTrace(); return false; } finally { manager.close(); }
您可以在Apache Commons VFS Documentation查看更多信息
编辑
在理解了FTPS背后的逻辑和@ riyaz-ali的帖子并将您的评论中的链接引用到this article之后
Apache FTP客户端存在问题,它不支持TLS会话恢复.您可以修补Apache Commons Library的现有实现.
您可以尝试以下代码步骤来使其工作:
>在项目中添加以下修补的类. (此类扩展了Apache commons中给出的补丁中现有的FTPS实现)
import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.Socket; import java.util.Locale; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocket; import org.apache.commons.net.ftp.FTPSClient; import com.google.common.base.Throwables; public class PatchedFTPSClient extends FTPSClient { @Override protected void _prepareDataSocket_(final Socket socket) throws IOException { if(socket instanceof SSLSocket) { final SSLSession session = ((SSLSocket) _socket_).getSession(); final SSLSessionContext context = session.getSessionContext(); try { final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache"); sessionHostPortCache.setAccessible(true); final Object cache = sessionHostPortCache.get(context); final Method method = cache.getClass().getDeclaredMethod("put",Object.class,Object.class); method.setAccessible(true); final String key = String.format("%s:%s",socket.getInetAddress().getHostName(),String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT); method.invoke(cache,key,session); } catch(Exception e) { throw Throwables.propagate(e); } } } }
TransferImagenesFTP.ftpClient = new PatchedFTPSClient(); TransferImagenesFTP.ftpClient.connect(InetAddress.getByName<SERVER-ADDRESS>"),26); TransferImagenesFTP.ftpClient.login("<USERNAME>","<PASSWORD>"); TransferImagenesFTP.ftpClient.execPBSZ(0); TransferImagenesFTP.ftpClient.execPROT("P"); TransferImagenesFTP.ftpClient.enterLocalPassiveMode(); //Now use the FTP client to upload the file as usual.
希望这对您有用,并将解决您的问题.