我在我的
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.
希望这对您有用,并将解决您的问题.