import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import java.io.*;
import java.text.ParseException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
/**
@Author Canaan
@Date 2018/3/22 */
@Service
public class ServiceImpl implements Service, ResourceLoaderAware {
private final static String FTP_PASSWORD = "isddsdfc";
private final static String FTP_URL = "ls.csdrt.com.cn";
private final static String FTP_USER_NAME = "idsfsc";
private final static Integer FTP_PORT = 21;
private final static String FTP_PATH = "cusdrwewnt/fosfsclock/"; //fpt目录
private final static String FTP_ENCODING = "gbk"; // 归档的文件编码
private final static String RESOURCE_FILE_DIR = "qefasd/current/foodclock/"; //下载路径
private final static String LOCAL_FILE_PATH = "F:\\Downloads\\"; //本地路径
private final Logger logger = LoggerFactory.getLogger(ServiceImpl.class);
private Resource resource;
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
resource = resourceLoader.getResource(RESOURCE_FILE_DIR);
}
/**
从ftp中下载归档<br>
测试下载时间:
<li>6798 ms</li><li>6528 ms</li><li>6528 ms</li>
<li>6523 ms</li><li>6554 ms</li><li>6479 ms</li>
@return
*/
@Override
public FamilyMartArchives downLoadFromFTP(Date date) throws IOException {
FTPClient ftpClient = new FTPClient();
try {
//1. 建立连接
ftpClient.connect(FTP_URL, FTP_PORT);
//打开FTP服务器
//登录
if (!ftpClient.login(FTP_USER_NAME, FTP_PASSWORD)) {
logger.error("ftp登录失败");
return null;
}
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
logger.error("ftp is not positiveCompletion");
return null;
}
//目录切换
if (!cd(ftpClient, FTP_PATH)) {
logger.error("ftp目录无效");
return null;
}
//文件预览,没有chk 文件就退出
String archivesFileName = null; //找出归档的文件
boolean flag = false;
String[] names = ftpClient.listNames();
if (ArrayUtils.isEmpty(names)) {
return null;
}
for (String name : names) {
if (StringUtils.containsIgnoreCase(name, "FOODCLOCK") && StringUtils.containsIgnoreCase(name, ".zip")) {
archivesFileName = name;
}
if (flag || StringUtils.containsIgnoreCase(name, ".chk")) {
flag = true;
}
}
if (!flag || StringUtils.isBlank(archivesFileName)) {
logger.error("ftp归档失败,没有【.chk】文件");
return null;
}
//文件下载
Map<String, List<String>> archives;
archives = loadFile(ftpClient, archivesFileName);
if (archives == null || archives.isEmpty()) {
return null;
}
//文件解析,返回归档文件
return analysis(archives);
} finally {
//关闭连接
closeFTP(ftpClient);
}
}
/**
归档文件解析
@param archives
@return
*/
private FamilyMartArchives analysis(Map<String, List<String>> archives) {
//
}
/**
目录切换
@param ftpClient
@param path
@return
*/
private boolean cd(FTPClient ftpClient, String path) {
try {
return ftpClient.changeWorkingDirectory(path);
} catch (IOException e) {
logger.error("切换目录失败【{}】", path, e);
return false;
}
}
/*
下载文件
*/
private Map<String, List<String>> loadFile(FTPClient ftpClient, String archivesFileName) throws IOException {
//TODO 如果本地文件已经存在,是否删除?
boolean flag = true;
// 下载文件
BufferedOutputStream buffOut = null;
try {
//锁的双重验证
if (resource != null && !resource.exists()) {
synchronized (RESOURCE_FILE_DIR) {
if (resource != null && !resource.exists()) {
flag = resource.getFile().mkdirs();
} else {
flag = true;
}
}
}
if (resource != null && flag) {
buffOut = new BufferedOutputStream(new FileOutputStream(resource.getFile()+"\\"+ archivesFileName));
} else {
buffOut = new BufferedOutputStream(new FileOutputStream(LOCAL_FILE_PATH + archivesFileName));
}
flag = ftpClient.retrieveFile(archivesFileName, buffOut);
} catch (Exception e) {
logger.error("ftp文件下载失败!", e);
return null;
} finally {
try {
if (buffOut != null) {
buffOut.flush();
buffOut.close();
}
} catch (Exception e) {
//
}
}
//文件解析
if(flag){
if (resource != null) {
return readFile(resource.getFile().getPath()+"\\"+archivesFileName);
} else {
return readFile(LOCAL_FILE_PATH + archivesFileName);
}
}
return null;
}
/**
读取归档文件的内容
@return
@throws IOException
*/
private Map<String, List<String>> readFile(String filePath) throws IOException {
Map<String, List<String>> result = new HashMap<>();
ZipFile zf = new ZipFile(filePath);
InputStream in = new BufferedInputStream(new FileInputStream(filePath));
ZipInputStream zin = new ZipInputStream(in);
//ZipEntry 类用于表示 ZIP 文件条目。
ZipEntry ze;
try {
while ((ze = zin.getNextEntry()) != null) {
if (ze.isDirectory()) {
continue;
}
if (ze.getSize() <= 0) {
continue;
}
List<String> rows = new ArrayList<>(); //记录数
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(zf.getInputStream(ze), FTP_ENCODING));
String contextLine;
while ((contextLine = reader.readLine()) != null) {
rows.add(contextLine);
}
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
//
}
}
result.put(ze.getName(), rows);
}
} finally {
try {
if (zin != null) {
zin.close();
}
if (in != null) {
in.close();
}
if (zf != null) {
zf.close();
}
} catch (IOException e) {
//
}
}
return result;
}
}