package com.fhresource.common.util
;
import com.fhresource.common.constants.Constants
;
import com.fhresource.common.entity.bo.FileAttribute
;
import com.fhresource.common.entity.vo.Result
;
import com.fhresource.common.ftp.FTPConstant
;
import org.apache.commons.collections.CollectionUtils
;
import org.apache.commons.net.PrintCommandListener
;
import org.apache.commons.net.ftp.FTP
;
import org.apache.commons.net.ftp.FTPClient
;
import org.apache.commons.net.ftp.FTPFile
;
import org.apache.commons.net.ftp.FTPReply
;
import java.io.IOException
;
import java.io.PrintWriter
;
import java.nio.charset.StandardCharsets
;
import java.util.ArrayList
;
import java.util.Date
;
import java.util.List
;
import java.util.logging.Logger
;
import java.util.stream.Collectors
;
/**
*
* @Author lzy
*/
public class FTPListAllFiles
{
private static Logger logger
= Logger.getLogger
(String.valueOf
(FTPListAllFiles.class
));
private FTPConstant ftpConstant
;
public FTPClient
ftp;
public ArrayList
<String
> arFiles
;
public FTPListAllFiles
(boolean isPrintCommmand
) {
ftp = new FTPClient
();
arFiles
= new ArrayList
<String
>();
if (isPrintCommmand
) {
ftp.addProtocolCommandListener
(new PrintCommandListener
(new PrintWriter
(System.out
)));
}
}
/**
* 登陆FTP服务器
*
* @param host FTPServer IP地址
* @param port FTPServer 端口
* @param username FTPServer 登陆用户名
* @param password FTPServer 登陆密码
* @return 是否登录成功
* @throws IOException
*/
public boolean login
(String host, int port, String username, String password
) throws IOException
{
this.ftp.connect
(host, port
);
if (FTPReply.isPositiveCompletion
(this.ftp.getReplyCode
())) {
if (this.ftp.login
(username, password
)) {
/**
需要注意这句代码,如果调用List
()方法出现,文件的无线递归,与真实目录结构不一致的时候,可能就是因为转码后,读出来的文件夹与正式文件夹字符编码不一致所导致。
则需去掉转码,尽管递归是出现乱码,但读出的文件就是真实的文件,不会死掉。等读完之后再根据情况进行转码。
如果ftp部署在windows下,则:
*/
this.ftp.setControlEncoding
("UTF-8");
return true;
}
}
if (this.ftp.isConnected
()) {
this.ftp.disconnect
();
}
return false;
}
/**
* 关闭数据链接
*
* @throws IOException
*/
public void disConnection
() throws IOException
{
if (this.ftp.isConnected
()) {
this.ftp.disconnect
();
}
}
public List
<FileAttribute
> setFileAttributeList
(List
<FileAttribute
> fileAttributeList, FileAttribute fileAttribute, FTPFile file, String filePath
){
fileAttribute.setFileName
(file.getName
());
fileAttribute.setFilePath
(filePath+file.getName
());
fileAttribute.setFileSize
(file.getSize
());
fileAttributeList.add
(fileAttribute
);
return fileAttributeList
;
}
/**
* 递归遍历出目录下面所有文件
*
* @param pathName 需要遍历的目录,必须以
"/"开始和结束
* @throws IOException
*/
public void List
(String pathName, List
<FileAttribute
> fileAttributeList,Integer parentId,Integer id
) throws IOException
{
if (pathName.startsWith
("/") && pathName.endsWith
("/")) {
//更换目录到当前目录
//this.ftp.changeWorkingDirectory
(new String
(pathName.getBytes
(), FTP.DEFAULT_CONTROL_ENCODING
));
this.ftp.changeWorkingDirectory
(new String
(pathName.getBytes
(), StandardCharsets.ISO_8859_1
));
FTPFile
[] files
= this.ftp.listFiles
();
List
<FileAttribute
> dirfileAttributeList
=new ArrayList
<>();
for (FTPFile
file : files
) {
FileAttribute fileAttribute
=new FileAttribute
();
fileAttribute.setParentId
(parentId
);
//判断是否是文件
if (file.isFile
()) {
fileAttribute.setIsfile
(Constants.FTP_FILE
);
//组装文件类
setFileAttributeList
(fileAttributeList,fileAttribute,file,pathName
);
} else if (file.isDirectory
()) {
id++
;
fileAttribute.setFileSize
(file.getSize
());
fileAttribute.setFileId
(id
);
fileAttribute.setFileName
(file.getName
());
fileAttribute.setIsfile
(Constants.FTP_FOLDER
);
fileAttribute.setFilePath
(pathName+file.getName
());
fileAttributeList.add
(fileAttribute
);
dirfileAttributeList.add
(fileAttribute
);
}
}
if (dirfileAttributeList
!=null
&&dirfileAttributeList.size
()>0
){
for ( FileAttribute fileAttribute :dirfileAttributeList
){
//save
(fileAttribute
);保存数据库返回主键id
parentId
=fileAttribute.getFileId
();
// 需要加此判断。否则,ftp默认将‘项目文件所在目录之下的目录(./)’与‘项目文件所在目录向上一级目录下的目录(
../)’都纳入递归,这样下去就陷入一个死循环了。需将其过滤掉。
if (!".".equals
(fileAttribute.getFileName
()) && !"..".equals
(fileAttribute.getFileName
())) {
List
(pathName + fileAttribute.getFileName
() +
"/",fileAttributeList,parentId,id
);
}
}
}
}
}
/**
* 递归遍历目录下面指定的文件名
*
* @param pathName 需要遍历的目录,必须以
"/"开始和结束
* @param ext 文件的扩展名
* @throws IOException
*/
public void List
(String pathName, String ext
) throws IOException
{
if (pathName.startsWith
("/") && pathName.endsWith
("/")) {
//更换目录到当前目录
this.ftp.changeWorkingDirectory
(new String
(pathName.getBytes
(), StandardCharsets.ISO_8859_1
));
//this.ftp.changeWorkingDirectory
(new String
(pathName.getBytes
(), FTP.DEFAULT_CONTROL_ENCODING
) );
FTPFile
[] files
= this.ftp.listFiles
();
for (FTPFile
file : files
) {
if (file.isFile
()) {
if (file.getName
().endsWith
(ext
)) {
arFiles.add
(pathName + file.getName
());
}
} else if (file.isDirectory
()) {
if (!".".equals
(file.getName
()) && !"..".equals
(file.getName
())) {
List
(pathName + file.getName
() +
"/", ext
);
}
}
}
}
}
public static Result testHello
() throws IOException
{
FTPListAllFiles f
= new FTPListAllFiles
(true
);
List
<FileAttribute
> fileAttributeList
=new ArrayList
<FileAttribute
>();
FileAttribute
file = new FileAttribute
();
file.setIsfile
(Constants.FTP_FOLDER
);
file.setFileId
(Constants.ONE
);
file.setParentId
(Constants.ZERO
);
file.setFileName
("**
**");
file.setFilePath
("/zhzyk");
fileAttributeList.add
(file
);
Integer parentId
=Constants.ONE
;
Integer id
=Constants.TWO
;
if (f.login
("ip", 21,
"用户名",
"密码")) {
f.List
("/mnt/data2/110ftp/zhzyk/", fileAttributeList, parentId, id
);
}
f.disConnection
();
List
<FileAttribute
> roots
= fileAttributeList.stream
().filter
(groupCategory -
> (groupCategory.getParentId
().equals
(0
))).collect
(Collectors.toList
());
List
<FileAttribute
> subs
= fileAttributeList.stream
().filter
(groupCategory -
> (groupCategory.getParentId
() != 0
)).collect
(Collectors.toList
());
roots.forEach
(root -
> buildSubs
(root, subs
));
return Result.success
(roots
);
}
/**
* 递归构建
* @param parent
* @param subs
*/
private static void buildSubs
(FileAttribute parent, List
<FileAttribute
> subs
) {
List
<FileAttribute
> children
= subs.stream
().filter
(sub -
> (sub.getParentId
() .equals
(parent.getFileId
()) )).collect
(Collectors.toList
());
//有子分类的情况
if (!CollectionUtils.isEmpty
(children
)) {
parent.setListenerList
(children
);
//再次递归构建
children.forEach
(child -
> buildSubs
(child, subs
));
}
}
}
不懂的可以问我,一起学习。