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));
}
}
}
不懂的可以问我,一起学习。