Java中实现ftp下载文件至本地(详细):
2020-09-13:今天记录一下java中实现ftp下载文件至本地的功能模块,同此与大家交流分享有什么不对的地方大家可以指出! |
1.FTP协议:
什么是FTP呢?FTP 是 TCP/IP 协议组中的协议之一,是英文File Transfer Protocol的缩写。 该协议是Internet文件传送的基础,它由一系列规格说明文档组成,目标是提高文件的共享性,提供非直接使用远程计算机,使存储介质对用户透明 和可靠高效地传送数据。简单的说,FTP就是完成两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上,称之为“下载 (download)”文件。若将文件从自己计算机中拷贝至远程计算机上,则称之为“上载(upload)”文件。 |
2.SSH工具
ssh---ftp----winscp----filezilla-----xftp---- |
上面呢简单介绍下ftp协议和一些使用的工具,这篇文章呢我在java中是用的sftp下载,那使用的类是ChannelSftp,言归正传,奉上自己的demo。。。。
1.连接
protected static Logger log = LoggerFactory.getLogger(FTPUtil.class);
public static final String NO_FILE = "No such file";
private ChannelSftp sftp = null;
private Session sshSession = null;
private String username;
private String password;
private String host;
private int port;
public FTPUtil(String host, int port, String username, String password) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
public ChannelSftp connect() throws FtpException {
log.info("尝试连接FTP {host=" + host + ",username=" + username + ",port=" + port + "}");
boolean connect = false;
JSch jsch = new JSch();
try {
int tryCountAll = 5;
int tryCount = 0;
while (tryCount++ < tryCountAll && !connect) {
if (tryCount > 1) {
try {
Thread.sleep(5000 * (tryCount - 1));
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("第" + tryCount + "次尝试连接FTP服务器");
}
sshSession = jsch.getSession(username, host, port);
sshSession.setPassword(password);
Properties properties = new Properties();
properties.put("StrictHostKeyChecking", "no");
sshSession.setConfig(properties);
sshSession.connect(50000);
Channel channel = sshSession.openChannel("sftp");
channel.connect(50000);
sftp = (ChannelSftp) channel;
if (sftp == null) {
log.info("FTP 服务器未连接");
connect = false;
} else {
log.info("连接 FTP 成功!");
connect = true;
}
}
} catch (JSchException e) {
throw new FtpException("连接 FTP 异常 : " + e.getMessage());
}
return sftp;
}
这一块呢我们走完了第一步,先去连接远程,代码中加了重试的逻辑(重新连接的意思),代码中一些类大家可以下去自行了解,本人就不啰嗦了哦(我这边使用的是ChannelSftp ,大家不妨可以试试另一个FtpClient这个类(大步骤都差不多))
2.批量下载(我这里就不啰嗦很多了直接贴了代码,大家可以搜其他的,比如删除,单个下载什么的有很多,我这里项目用到的是一个批量下载,所以就贴出了一段代码!)
public void createDirectoryQuietly(File file) {
if (file != null) {
if (!file.exists()) {
if (!file.mkdirs()) {
throw new RuntimeException(file.getName() + " is invalid,can't be create directory");
}
}
}
}
public File downloadFileNew(String remoteDir, String localFile) throws FtpException {
long startTime = System.currentTimeMillis();
connect();
log.info("开始下载文件FTP目录 " + remoteDir + " 本地文件 " + localFile);
File file = null;
file = new File(localFile);
createDirectoryQuietly(file);
OutputStream output = null;
try {
sftp.cd(remoteDir);
String path = remoteDir + "/custInfo";
Vector v = sftp.ls(path);
List<String> filenameNew = new ArrayList<>();
if (v.size() > 0) {
log.info("文件个数不为0,开始下载。。。。。。。。。filesize=" + v.size());
Iterator it = v.iterator();
while (it.hasNext()) {
ChannelSftp.LsEntry lsentry = (ChannelSftp.LsEntry) it.next();
String filenames = lsentry.getFilename();
if (!".".equals(filenames) && !"..".equals(filenames)) {
log.info(path + "路径下的文件名" + filenames);
filenameNew.add(filenames);
}
}
} else {
log.info("获取文件失败 " + remoteDir + "文件数为0");
throw new FtpException("获取文件失败 " + remoteDir + "文件数为0");
}
sftp.cd(path);
for (int i = 0; i < filenameNew.size(); i++) {
System.out.println(filenameNew.get(i) + "文件名");
Vector<?> vNew = sftp.ls(filenameNew.get(i));
sftp.cd(filenameNew.get(i));
File file2=new File(localFile+"/"+filenameNew.get(i));
if (file2.exists()) {
file2.delete();
}
file2.mkdir();
if (vNew.size() > 0) {
Iterator it = vNew.iterator();
while (it.hasNext()) {
ChannelSftp.LsEntry lsentry = (ChannelSftp.LsEntry) it.next();
String filenames1 = lsentry.getFilename();
if (!".".equals(filenames1) && !"..".equals(filenames1)) {
log.info(filenameNew.get(i) + "路径下的文件名" + filenames1);
File file1 = new File(file2+"/"+filenames1);
file1.createNewFile();
output = new FileOutputStream(file1);
sftp.get(filenames1, output);
log.info("文件:" + filenames1 + " 下载成功.");
}
}
sftp.cd(path);
}
}
} catch (SftpException e) {
if (e.toString().equals(NO_FILE)) {
log.info("下载文件失败");
throw new FtpException("下载文件失败");
}
throw new FtpException("ftp目录或者文件异常,检查ftp目录和文件" + e.toString());
} catch (FileNotFoundException e) {
throw new FtpException("本地目录异常,请检查" + file.getPath() + e.getMessage());
} catch (IOException e) {
throw new FtpException("创建本地文件失败" + file.getPath() + e.getMessage());
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
throw new FtpException("Close stream error." + e.getMessage());
}
}
disconnect();
}
log.info("下载文件结束 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
return file;
}
给大家解释下代码
第一句 sftp.cd()这个方法大家都知道,cd进去目录(注意:关键点大家注意一下:当你想操作某个目录文件时一定要cd到这个目录下(啰嗦,跟谁不知道一样))
第三句 sfpt.ls()这个方法,大家也都知道哈,查看文件。往后代码的话就是使用循环将目录下的文件名循环出来,我这边使用list集合存了起来(注意:因为我当时要取得文件是 多层级目录的大家如果不是多层级的话,直接走你逻辑就好。)
这样的多层级目录的!
第二段代码
这一段呢,顾名思义,因为我的第一段代码呢是获取多层级的目录名字,那么这一段就是获取多层级目录下的文件。注意:上面代码的最后一段 那个cd方法。操作多层级目录你每进去一个目录,然后换另一个的话你就要在代码里,在cd下一个目录路径!
今天的这个ftp下载分享完了,大家如果有什么不太懂的地方,欢迎评论提出,我这会秒回哦!也谢谢大家的支持!记录生活,记录知识!我是王不正!