package com.web.util;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.*;
import java.util.Enumeration;
import java.util.Set;
import java.util.zip.*;
public class FtpUtil {
public static final String ENCODING_DEFAULT = "UTF-8";
public static final String ENCODING_GBK = "GBK";
public final static Integer BUFFER_SIZE_DEFAULT = 1024;
/**
* 描述:将Ftp上文件夹打包成.zip文件
* @param ftp ftp
* @param ftpPath ftp文件夹目录
* @param zipFilePath .zip文件目录 可以是本地或服务器
* @param fNameSet Ftp文件夹中需要压缩的文件名称Set集合
* @return
*/
public static void zipFile(FTPClient ftp, String ftpPath, String zipFilePath, Set<String> fNameSet)
throws IOException
{
//创建zip输出流
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
// 转移到FTP服务器目录
ftp.changeWorkingDirectory(ftpPath);
// 将目录下所有文件、文件夹取出压缩
FTPFile[] fs = ftp.listFiles();
for (FTPFile f : fs) {
compress(zipOut, ftp, f, f.getName(), ftpPath, fNameSet);
}
FtpUtil.closeFtp(ftp);
}
public static void compress(ZipOutputStream out, FTPClient ftp, FTPFile sourceFile, String base, String workingDirectory, Set<String> fNameSet)
throws IOException
{
//如果路径为目录(文件夹)
if(sourceFile.isDirectory()) {
//取出文件夹中的文件(或子文件夹)
workingDirectory = workingDirectory + File.separator + sourceFile.getName();
// change working Directory
ftp.changeWorkingDirectory(workingDirectory);
FTPFile[] flist = ftp.listFiles();
out.putNextEntry(new ZipEntry(base + File.separator));
// 如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
for (FTPFile ftpFile : flist) {
compress(out, ftp, ftpFile, base + File.separator + ftpFile.getName(), workingDirectory, fNameSet);
}
} else {
// 只对文件名处理 若文件名存在set集合中就进行压缩 否则就不压
if(fNameSet.isEmpty()||fNameSet.contains(sourceFile.getName())){
out.putNextEntry(new ZipEntry(base));
// ByteArrayOutputStream os = new ByteArrayOutputStream();
String downFileName = new String(sourceFile.getName().getBytes("GBK"), "ISO-8859-1");
ftp.changeWorkingDirectory(workingDirectory);
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
// ftp.retrieveFile(downFileName, os);
// byte[] bytes = os.toByteArray();
// InputStream ins = new ByteArrayInputStream(bytes);
InputStream ins = ftp.retrieveFileStream(downFileName);
int len;
byte[] buf = new byte[1024];
while((len=ins.read(buf, 0, 1024)) != -1) {
out.write(buf, 0, len);
}
ins.close();
}
}
out.flush();
}
/**
* 描述 : 读取FTP上文件中内容文件中json数据
* @param ftp
* @param fileName
* @param ftpDir
* @return
*/
public static String readFileContentFromFtp(FTPClient ftp, String fileName, String ftpDir) throws IOException {
StringBuffer Contents = new StringBuffer("");
ftp.changeWorkingDirectory(ftpDir);
InputStream is = ftp.retrieveFileStream(fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String readContentLine = null;
// 一次读入一行,直到读入null为文件结束
while ((readContentLine = reader.readLine()) != null) {
Contents.append(System.lineSeparator() + readContentLine);
}
// 关闭reader
reader.close();
is.close();
return Contents.toString();
}
/**
* 描述:将本地文件夹上传至ftp
* @param ftp
* @param file 本地文件夹、文件
* @param remotePath Ftp目录
*/
public void putDirectoryToFtp(FTPClient ftp, File file, String remotePath){
try{
ftp.changeWorkingDirectory(remotePath);
File[] files = file.listFiles();
for (File f : files) {
doMethodPut(ftp, f, remotePath);
}
}catch (Exception e){
e.printStackTrace();
}
}
public void doMethodPut(FTPClient ftp, File file, String remotePath){
try{
if(file.isDirectory()){
// 判断ftp是否存在此文件夹,否则就要创建此文件夹。
String workingSpace = remotePath + file.getName() + File.separator;
ftp.changeWorkingDirectory(remotePath);
if(!ftp.changeWorkingDirectory(workingSpace)){
ftp.makeDirectory(file.getName());
}
File[] tfs = file.listFiles();
for(File f1 : tfs) {
doMethodPut(ftp, f1, workingSpace);
}
}else{
// 切换目录
ftp.changeWorkingDirectory(remotePath);
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.storeFile(file.getName(), new FileInputStream(file));
}
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 描述:删除FTP上文件夹
* @param ftp ftp
* @param remotePath Ftp文件夹目录
*/
private static void delFtpFolder(FTPClient ftp, String remotePath) throws IOException {
if(ftp.changeWorkingDirectory(remotePath)){
FTPFile[] files = ftp.listFiles();
for (FTPFile file : files) {
doMethodDel(ftp, file, remotePath);
}
}
}
private static void doMethodDel(FTPClient ftp, FTPFile file, String remotePath) throws IOException {
if(file.isDirectory()){
if(null == file){
ftp.deleteFile(file.getName());
}else{
String workingSpace = remotePath + file.getName() + File.separator;
ftp.changeWorkingDirectory(workingSpace);
FTPFile[] tfs = ftp.listFiles();
for(FTPFile f1 : tfs) {
doMethodDel(ftp, f1, workingSpace);
}
}
ftp.changeWorkingDirectory(remotePath);
ftp.removeDirectory(file.getName());
}else {
ftp.changeWorkingDirectory(remotePath);
ftp.deleteFile(file.getName());
}
}
// 上传文件到 服务器
public static void putFileToServer(InputStream is, String serviceFilePath)
throws IOException
{
OutputStream os = new FileOutputStream(serviceFilePath);
byte[] b = new byte[BUFFER_SIZE_DEFAULT];
int c = 0 ;
while ( (c = is.read(b)) != -1 ) {
os.write(b,0,c);
os.flush();
}
os.flush();
os.close();
}
/**
* 描述:在服务器上 解压.zip文件,
* 不能解决压缩包中文件夹或文件名称为中文的场景,就是zipIs.getNextEntry() 读到的是中文会直接抛异常。
* 所以将方法修改为 org.apache.tools.zip.ZipEntry 含有中文的压缩包解压使用ApacheAntUtilUnZip方法。
* @param zipFilePath
* @param extPlace
* @throws IOException
*/
public static void extZipFileOnService(String zipFilePath, String extPlace) throws IOException {
FileInputStream is = new FileInputStream(new File(zipFilePath));
ZipInputStream zipIs = new ZipInputStream(is);
ZipEntry entry = null;
while ((entry = zipIs.getNextEntry()) != null){
String entryName = entry.getName();
// System.out.println("entryName= "+ entryName);
if (entryName.endsWith("/")||entryName.endsWith("\\")||entry.isDirectory()) {
File file = new File(extPlace + entryName);
file.mkdirs();
} else {
FileOutputStream os = new FileOutputStream(extPlace + entryName);
// Transfer bytes from the ZIP file to the output file
byte[] buf = new byte[BUFFER_SIZE_DEFAULT];
int len;
while ((len = zipIs.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, len);
}
// 关闭流
os.close();
}
}
is.close();
zipIs.close();
}
public static void ApacheAntUtilUnZip(String zipFilePath, String storePath)
throws IOException {
ApacheAntUtilUnZip(new File(zipFilePath), storePath);
}
public static void ApacheAntUtilUnZip(File zipFile, String storePath) throws IOException
{
if (new File(storePath).exists()) {
new File(storePath).delete();
}
new File(storePath).mkdirs();
org.apache.tools.zip.ZipFile zip = new org.apache.tools.zip.ZipFile(zipFile, ENCODING_GBK);
Enumeration<? extends org.apache.tools.zip.ZipEntry> enumeration =
(Enumeration<org.apache.tools.zip.ZipEntry>) zip.getEntries();
while (enumeration.hasMoreElements())
{
org.apache.tools.zip.ZipEntry zipEntry = (org.apache.tools.zip.ZipEntry)enumeration.nextElement();
if (!zipEntry.isDirectory()) {
// System.out.println("文件:"+ zipEntry.getName());
String zipEntryName = zipEntry.getName();
if (zipEntryName.indexOf(File.separator) > 0) {
String zipEntryDir = zipEntryName.substring(0, zipEntryName.lastIndexOf(File.separator) + 1);
String unzipFileDir = storePath + File.separator + zipEntryDir;
File unzipFileDirFile = new File(unzipFileDir);
if (!unzipFileDirFile.exists()) {
unzipFileDirFile.mkdirs();
}
}
InputStream is = zip.getInputStream(zipEntry);
FileOutputStream fos = new FileOutputStream(new File(storePath + File.separator + zipEntryName));
byte[] buff = new byte[BUFFER_SIZE_DEFAULT];
int size;
while ((size = is.read(buff, 0, buff.length)) > 0) {
fos.write(buff, 0, size);
}
fos.flush();
fos.close();
is.close();
}
}
}
/**
* 描述: 从ftp上下载文件(至本地、服务器)
* @param ftpClient ftp
* @param ftpFilePath ftp文件所在目录
* @param osPath 压缩包地址
* @param fileName 要下载的文件名称
* 修改记录:1.提高下载时效, 将下载方法FTPClient 的.retrieveFile 修改为ftpClient.retrieveFileStream
*/
public static void downLoadFileFromFtp(FTPClient ftpClient, String ftpFilePath, String osPath, String fileName)
throws IOException
{
InputStream inputStream = null;
OutputStream os = null;
os = new FileOutputStream(osPath);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 开启远程被动 传输数据
ftpClient.enterLocalPassiveMode();
if (ftpClient.changeWorkingDirectory(ftpFilePath)) {
// FTPFile[] ftpFiles = ftpClient.listFiles();
// for (int i = 0; i < ftpFiles.length; i++) {
// if(fileName.equals(ftpFiles[i].getName())){
// ftpClient.retrieveFile(new String(ftpFiles[i].getName().getBytes("GBK"),"ISO-8859-1"), os);
// os.flush();
// break;
// }
// }
inputStream = ftpClient.retrieveFileStream(new String(fileName.getBytes("GBK"), "ISO-8859-1"));
byte[] buf = new byte[BUFFER_SIZE_DEFAULT];
int len;
while ((len = inputStream.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, len);
}
inputStream.close();
}
os.close();
}
/**
* 描述:将目标文件(本地、服务器)上传至ftp
* @param filePath 目标文件全路径
* @param ftpFilePath Ftp目录
* @param fileName 文件名称
*/
public static void uploadFile2Ftp(FTPClient ftpClient, String filePath, String ftpFilePath, String fileName)
throws IOException
{
FileInputStream is = new FileInputStream(new File(filePath));
// 开启远程被动传输模式
// ftpClient.enterRemotePassiveMode();
// 切换目录
ftpClient.changeWorkingDirectory(ftpFilePath);
ftpClient.setControlEncoding(ENCODING_GBK);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");
ftpClient.storeFile(fileName, is);
is.close();
}
// 从新压缩 返回给移动端
private static void buildZip(String fDirectory, String newZipFilePath, Set needZipSet) throws IOException {
ZipOutputStream zipOutputStream = null;
zipOutputStream = new ZipOutputStream(new FileOutputStream(new File(newZipFilePath)));
File file = new File(fDirectory);
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
buildZipOut(zipOutputStream, f, f.getName(), needZipSet);
}
}
zipOutputStream.close();
}
public static void buildZipOut(ZipOutputStream zipOutputStream, File file, String base, Set needZipSet) throws IOException {
if (file.isDirectory()) {
File[] files = file.listFiles();
// if (files.length == 0) {
// zipOutputStream.putNextEntry(new ZipEntry(base + File.separator));
// } else {
// for (int i = 0; i < files.length; i++) {
// buildZipOut(zipOutputStream, files[i], base + File.separator + files[i].getName(), needZipSet);
// }
// }
zipOutputStream.putNextEntry(new ZipEntry(base + File.separator));
if (files != null) {
for (File f : files) {
buildZipOut(zipOutputStream, f, base + File.separator + f.getName(), needZipSet);
}
}
} else {
if (needZipSet.isEmpty() || needZipSet.contains(file.getName())) {
zipOutputStream.putNextEntry(new ZipEntry(base));
InputStream is = new FileInputStream(file);
int len;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes, 0, 1024)) != -1) {
zipOutputStream.write(bytes, 0, len);
}
is.close();
}
}
}
public static void closeFtp(FTPClient ftp){
try {
ftp.logout();
ftp.disconnect();
System.out.println("FtpBean logout...");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (ftp.isConnected()) {
try {
ftp.logout();
ftp.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static FTPClient connectFTP(String ip, int port, String userName, String password)
{
try{
FTPClient ftp = new FTPClient();
ftp.connect(ip, port);
//下面三行代码必须要,而且不能改变编码格式
ftp.setControlEncoding(ENCODING_GBK);
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");
//如果采用默认端口,可以使用ftp.connect(url) 的方式直接连接FTP服务器
ftp.login(userName, password);//登录
System.out.println("FtpBean login success...");
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return null;
}
return ftp;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}