在本文中,我们将带你了解使用org.apache.commons.net.ftp.FTPClient保护FTP在这篇文章中,我们将为您详细介绍使用org.apache.commons.net.ftp.
在本文中,我们将带你了解使用org.apache.commons.net.ftp.FTPClient保护FTP在这篇文章中,我们将为您详细介绍使用org.apache.commons.net.ftp.FTPClient保护FTP的方方面面,并解答ftp怎么保护用户名密码常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Apache Commons FTPClient.listFiles、Apache Commons FTPClient挂起、Apache Commons Net FTPClient和listFiles()、apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池。
本文目录一览:- 使用org.apache.commons.net.ftp.FTPClient保护FTP(ftp怎么保护用户名密码)
- Apache Commons FTPClient.listFiles
- Apache Commons FTPClient挂起
- Apache Commons Net FTPClient和listFiles()
- apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池
使用org.apache.commons.net.ftp.FTPClient保护FTP(ftp怎么保护用户名密码)
有什么办法可以实现安全的FTP org.apache.commons.net.ftp.FTPClient
?
如果没有,那么Java还有哪些其他选择?
答案1
小编典典您可以使用org.apache.commons.net.ftp。 FTPSClient,
而不是org.apache.commons.net.ftp。 FTPClient 具有安全的ftp
http://commons.apache.org/proper/commons-
net/apidocs/org/apache/commons/net/ftp/FTPSClient.html
Apache Commons FTPClient.listFiles
我org.apache.commons.net.ftp.FTPClient
在一个应用程序中使用FTP服务器。我能够connect,login,pwd和cwd。但是,当我尝试list文件时,它不会返回该目录中的文件列表,我肯定知道该目录中有文件。我正在使用方法FTPFile[] listFiles()
,它返回的空数组FTPFile。
请在我正在尝试的代码段下面找到:
String hostname = properties.getProperty("FTP_SERVER");
String user = properties.getProperty("FTP_USER");
String passwd = properties.getProperty("FTP_PASSWD");
FTPClient client = new FTPClient();
client.connect(hostname);
client.login(user,passwd);
String reply = client.getStatus();
System.out.println(reply);
client.enterRemotePassiveMode();
client.changeWorkingDirectory("/uploads");
FTPFile[] files = client.listFiles();
System.out.println(files.length);
for (FTPFile file : files) {
System.out.println(file.getName());
}
String[] fileNames = client.listNames();
if (fileNames != null) {
for (String file : fileNames) {
System.out.println(file);
}
}
client.disconnect();
Apache Commons FTPClient挂起
我们使用以下Apache Commons Net FTP代码连接到FTP服务器,轮询某些目录中的文件,如果找到文件,则将它们检索到本地计算机:
try {logger.trace("Attempting to connect to server...");// Connect to serverFTPClient ftpClient = new FTPClient();ftpClient.setConnectTimeout(20000);ftpClient.connect("my-server-host-name");ftpClient.login("myUser", "myPswd");ftpClient.changeWorkingDirectory("/loadables/");// Check for failed connectionif(!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){ ftpClient.disconnect(); throw new FTPConnectionClosedException("Unable to connect to FTP server.");}// Log success msglogger.trace("...connection was successful.");// Change to the loadables/ directory where we poll for filesftpClient.changeWorkingDirectory("/loadables/");// Indicate we''re about to polllogger.trace("About to check loadables/ for files...");// Poll for files.FTPFile[] filesList = oFTP.listFiles();for(FTPFile tmpFile : filesList){ if(tmpFile.isDirectory()) continue; FileOutputStream fileOut = new FileOutputStream(new File("tmp")); ftpClient.retrieveFile(tmpFile.getName(), fileOut); // ... Doing a bunch of things with output stream // to copy the contents of the file down to the local // machine. Ommitted for brevity but I assure you this // works (except when the WAR decides to hang). // // This was used because FTPClient doesn''t appear to GET // whole copies of the files, only FTPFiles which seem like // file metadata...}// Indicate file fetch completed.logger.trace("File fetch completed.");// Disconnect and finish.if(ftpClient.isConnected()) ftpClient.disconnect();logger.trace("Poll completed.");} catch(Throwable t) { logger.trace("Error: " + t.getMessage());}
我们计划将其每分钟运行一次。当部署到Tomcat(7.0.19)时,此代码可以很好地加载并开始正常运行。但是,每次似乎都在 挂起 。我的意思是:
- 不存在堆转储
- Tomcat仍在运行(我可以看到其pid并可以登录到Web Manager应用程序)
- 在管理器应用程序中,我可以看到我的WAR仍在运行/启动
catalina.out
而且我的应用程序专用日志没有任何异常抛出的迹象
因此,JVM仍在运行。Tomcat仍在运行,而我部署的WAR仍在运行,但是它刚刚挂起。有时它会运行2个小时,然后挂起。有时它会运行几天然后挂起。但是当它挂起时,它会在读取的行Aboutto check loadables/ for files...
(我确实在日志中看到)和读取的行File fetchcompleted.
(我没有看到)之间这样做。
这告诉我挂起发生在实际轮询/获取文件的过程中,这种情况使我指出了与该问题相同的方向,这个问题使我能够找到与FTPClient死锁有关的问题。这让我想知道这些是否是相同的问题( 如果是的话,我会很乐意删除此问题!
)。不过,我不认为 认为 它们是相同的(我没有看到我日志中的同样的例外)。
一位同事提到这可能是“被动”与“主动”
FTP的问题。没有真正知道的区别,我由FTPClient领域糊涂一点ACTIVE_REMOTE_DATA_CONNECTION_MODE
,PASSIVE_REMOTE_DATA_CONNECTION_MODE
等等,不知道为什么情绪这么想过,作为一个潜在的问题。
由于我在Throwable
这里是不得已而为之的方法,因此,如果出现问题,我本可以期望在日志中看到 某些内容 。嗯,我觉得这绝对是个难题。
有任何想法吗?不幸的是,我对FTP的内部知识了解不足,无法做出可靠的诊断。这可能是服务器端的东西吗?与FTP服务器相关?
答案1
小编典典这可能有很多事情,但是您朋友的建议是值得的。
尝试ftpClient.enterLocalPassiveMode();
看看是否有帮助。
我还建议 将断开连接放在finally
块中,以使其永远不会留下连接。
Apache Commons Net FTPClient和listFiles()
谁能解释以下代码有什么问题?我尝试了其他主机FTPClientConfigs,可以通过firefox /
filezilla正确访问它。问题是我总是得到空的文件列表,没有任何异常(files.length == 0)。我使用随Maven安装的commons-
net-2.1.jar。
FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_L8); FTPClient client = new FTPClient(); client.configure(config); client.connect("c64.rulez.org"); client.login("anonymous", "anonymous"); client.enterRemotePassiveMode(); FTPFile[] files = client.listFiles(); Assert.assertTrue(files.length > 0);
答案1
小编典典找到了!
问题是您想 在连接之后但在登录之前进入被动模式 。您的代码对我没有任何回报,但这对我有用:
import org.apache.commons.net.ftp.FTPClient;import java.io.IOException;import org.apache.commons.net.ftp.FTPFile;public class BasicFTP { public static void main(String[] args) throws IOException { FTPClient client = new FTPClient(); client.connect("c64.rulez.org"); client.enterLocalPassiveMode(); client.login("anonymous", ""); FTPFile[] files = client.listFiles("/pub"); for (FTPFile file : files) { System.out.println(file.getName()); } }}
给我这个输出:
c128c64c64.hu传入加4
apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池
commons-net 包介绍
commons-net 是 apachecommons 用于网络的工具包,它实现了一些常见的网络工具,如 smtp
,pop3
,telnet
,ftp
,udp
等,本文主要使用它的 ftp 工具。
使用 FTP 工具时的问题
在使用 commons-net 提供的 ftp 工具的时候 ,发现每次都要走一遍完整的连接,登录流程。每次都创建连接的话,很快就会把连接耗光,如果使用单例,则效率过低,因为只有一个连接,所以考虑用对象池的方式。
自已定义对象池的话,我之前有弄过,但要考虑好多的问题。像线程池一样,需要考虑核心对象数、最大对象数、何时创建对象 、及队列等,这时可以使用 apache 的 commons-pool2 来做一个对象池。
重要说明 : FTPClient 每次使用都需要重新连接,不然它会自动断开连接,使用会直接返回 421 ,本文章只是给个使用 commons-pool2 对象池的示例。
如何使用 commons-pool2
可以这么想,如果我要做个对象池的工具给别人用,首先要考虑的是池子里装的什么,用户要如何创建池子里的对象,然后提供方法借对象和回收对象,我可以把池子中的对象抽象出来,由一个工厂统一管理,用户的对象从我的通用对象继承或实现,或使用聚合方式 。
其实 spring-data-redis 已经给我们一个完整的使用 commons-pool2 的例子,它就是用的 commons-pool2 ,它的池中对象是 redis 连接,有兴趣可以去瞧瞧。
定义池中对象 FTPClient 的扩展对象
因为 FTPClient 的功能太过简单,连多层目录时自己创建目录都不会,所以有必要给它包装一下,这里你可以扩展常用到的方法。
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
@Slf4j
public class FtpClientExtend {
private FTPClient ftpClient ;
public FtpClientExtend(FTPClient ftpClient) {
this.ftpClient = ftpClient;
}
/**
* 列出文件列表
* @param filePath
* @return
* @throws IOException
*/
public FTPFile[] listFiles(String filePath) throws IOException {
return ftpClient.listFiles(filePath);
}
/**
* 下载文件
* @param filePath
* @return
*/
public InputStream downloadFile(String filePath) throws IOException {
return ftpClient.retrieveFileStream(filePath);
}
/**
* 存储文件
* @param s
* @param inputStream
*/
public void uploadFile(String filePath, InputStream inputStream) throws IOException {
File targetFilePath = new File(filePath);
Path path = targetFilePath.getParentFile().toPath();
Iterator<Path> iterator = path.iterator();
StringBuffer root = new StringBuffer("");
while (iterator.hasNext()){
Path next = iterator.next();
root.append("/").append(next);
//尝试切入目录
boolean success = ftpClient.changeWorkingDirectory(root.toString());
if(!success){
int mkd = ftpClient.mkd(next.toString());
ftpClient.changeWorkingDirectory(root.toString());
}
}
ftpClient.enterLocalPassiveMode();
ftpClient.setControlEncoding("UTF-8");
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
boolean storeFileResult = ftpClient.storeFile(targetFilePath.getName(), inputStream);
if (storeFileResult) {
log.debug("上传文件:" + filePath + ",到目录:" + ftpClient.printWorkingDirectory() + " 成功");
}else{
log.debug("上传文件:" + filePath + ",到目录:" + ftpClient.printWorkingDirectory() + " 失败");
}
}
}
使用聚合包裹池中对象
这个包裹对象的类才是工厂真正产生在池中的类,文末给出图示
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class FtpClientPool extends GenericObjectPool<FtpClientExtend> {
public FtpClientPool(PooledObjectFactory<FtpClientExtend> factory) {
super(factory);
}
public FtpClientPool(PooledObjectFactory<FtpClientExtend> factory, GenericObjectPoolConfig config) {
super(factory, config);
}
}
建立创建对象的工厂
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
public class FtpClientFactory extends BasePooledObjectFactory<FtpClientExtend> {
@Value("${ftp.host:localhost}")
private String host;
@Value("${ftp.port:21}")
private int port;
@Value("${ftp.username:ftpadmin}")
private String username;
@Value("${ftp.password:salt202}")
private String password;
@Override
public FtpClientExtend create() throws Exception {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(host,port);
boolean login = ftpClient.login(username, password);
if(!login){
throw new RuntimeException("ftp 登录失败,检查用户名密码是否正确["+host+":"+port+"]["+username+"]["+password+"]");
}
return new FtpClientExtend(ftpClient);
}
@Override
public PooledObject<FtpClientExtend> wrap(FtpClientExtend ftpClientExtend) {
return new DefaultPooledObject(ftpClientExtend);
}
}
使用方法
@Autowired
private FtpClientPool ftpClientPool;
public void method(){
FtpClientExtend ftpClientExtend = null;
try{
ftpClientExtend = ftpClientPool.borrowObject();
}finally{
if(ftpClientExtend != null) {
ftpClientPool.returnObject(ftpClientExtend);
}
}
}
原理图示
今天的关于使用org.apache.commons.net.ftp.FTPClient保护FTP和ftp怎么保护用户名密码的分享已经结束,谢谢您的关注,如果想了解更多关于Apache Commons FTPClient.listFiles、Apache Commons FTPClient挂起、Apache Commons Net FTPClient和listFiles()、apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池的相关知识,请在本站进行查询。
本文标签: