ftp上传文件,下载文件,断点续传,进度条,新建,删除文件,文件夹,工具@TOC
package com.css.sword.yhzx.common;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.text.NumberFormat;
import java.util.Map;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.eclipse.jetty.util.log.Log;
import com.css.sword.kernel.base.exception.SwordBaseCheckedException;
public class FtpUtils {
private static Logger logger = Logger.getLogger(FtpUtils.class);
private static FTPClient ftp;
private static String LOCAL_CHARSET = "UTF-8";
private static String SERVER_CHARSET = "ISO-8859-1";
private static OutputStream os = null;
/**
* 获取ftp连接
*
* @param f
* @return
* @throws Exception
*/
public static boolean connectFtp(Map<String, Object> paramMap) throws Exception {
ftp = new FTPClient();
boolean flag = false;
int reply;
String ipAddress = (String) paramMap.get("ftpurl");
Integer port = (Integer) paramMap.get("port");
String userName = (String) paramMap.get("username");
String password = (String) paramMap.get("password");
if (port == null) {
ftp.connect(ipAddress, 21);
} else {
ftp.connect(ipAddress, port);
}
ftp.login(userName, password);
ftp.enterLocalPassiveMode();
// ftpClient.enterLocalActiveMode();// 主动模式
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.setDataTimeout(60000); // 设置传输超时时间为60秒
ftp.setConnectTimeout(60000); // 连接超时为60秒
reply = ftp.getReplyCode();
/*if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
LOCAL_CHARSET = "UTF-8";
}*/
ftp.setControlEncoding(LOCAL_CHARSET);
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return flag;
}
ftp.changeWorkingDirectory("/");
flag = true;
return flag;
}
/**
* 关闭ftp连接
*/
public static void closeFtp() {
if (ftp != null && ftp.isConnected()) {
try {
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
}
}
/**
* ftp上传文件
*
* @param f
* @throws Exception
*/
public static void upload1(File f,String pathName) throws Exception {
ftp.changeWorkingDirectory(new String(pathName.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
if (f.isDirectory()) {
ftp.makeDirectory(f.getName());
ftp.changeWorkingDirectory(f.getName());
String[] files = f.list();
for (String fstr : files) {
File file1 = new File(f.getPath() + "/" + fstr);
if (file1.isDirectory()) {
upload1(file1,pathName);
ftp.changeToParentDirectory();
} else {
File file2 = new File(f.getPath() + "/" + fstr);
FileInputStream input = new FileInputStream(file2);
ftp.storeFile(new String(file2.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET), input);
input.close();
}
}
} else {
ftp.setBufferSize(1024*1024);
File file2 = new File(f.getPath());
FileInputStream inputStream = new FileInputStream(file2);
BufferedInputStream input = new BufferedInputStream(inputStream);
ftp.storeFile(new String(file2.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET), input);
input.close();
}
closeFtp();
}
/**
* FTP下载文件
*
* @param pathname
* 目标文件目录路径
* @param filename
* 文件名称(带后缀)
* @param localpath
* 本地存放路径
* @return
*/
public static boolean downloadFile(String pathname, String filename, String localpath) {
boolean flag = false;
try {
String newPathName = new String(pathname.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
flag =ftp.changeWorkingDirectory(newPathName);
// 读取文件
FTPFile[] ftpFiles = ftp.listFiles();
for (FTPFile file : ftpFiles) {
if (filename.equalsIgnoreCase(file.getName())) {
File localFile = new File(localpath);
if (!localFile.exists()) {
localFile.mkdirs();
}
localFile = new File(localpath + File.separator + file.getName());
os = new FileOutputStream(localFile);
ftp.retrieveFile(new String(file.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET), os);
os.close();
}
}
flag = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
closeFtp();
}
return flag;
}
/**
* 新建文件夹
*/
public static boolean createDir(String remote) throws UnsupportedEncodingException, IOException {
if(!remote.endsWith("/")){
remote = remote + "/";
}
boolean flag= false;
String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
if (!directory.equalsIgnoreCase("/") && !ftp.changeWorkingDirectory(
new String(directory.getBytes(LOCAL_CHARSET), SERVER_CHARSET))) {
// 如果远程目录不存在,则递归创建远程服务器目
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf("/", start);
while (true) {
String subDirectory = new String(remote.substring(start, end).getBytes(LOCAL_CHARSET), SERVER_CHARSET);
if (!ftp.changeWorkingDirectory(subDirectory)) {
if (ftp.makeDirectory(subDirectory)) {
flag=ftp.changeWorkingDirectory(subDirectory);
} else {
logger.debug("创建目录失败");
}
}else{
flag = true;
}
start = end + 1;
end = directory.indexOf("/", start);
// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
}else{
flag = true;
}
closeFtp();
return flag;
}
/**
* * 删除文件 *
*
* @param pathname
* FTP服务器保存目录 *
* @param filename
* 要删除的文件名称 *
* @param ftp
* @return
* @throws UnsupportedEncodingException
*/
public static boolean deleteFile(String pathname, String filename) throws UnsupportedEncodingException {
boolean flag = false;
String newPathName = new String(pathname.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
String newfilename = new String(filename.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
try {
//Logger.getLogger("开始删除文件");
// 切换FTP目录
/*String curDirectory = ftp.printWorkingDirectory();
if ("".equals(curDirectory)) {// 若为空,则定位到根目录
curDirectory = "";
}*/
ftp.changeWorkingDirectory( "/");
// 删除文件
flag =ftp.changeWorkingDirectory( newPathName);// 转移到FTP服务器目录
// ftp.changeWorkingDirectory(pathname);
flag =ftp.deleteFile(newfilename);
// ftp.logout();// 退出登录
logger.debug("删除文件成功");
} catch (Exception e) {
logger.debug("删除文件失败");
e.printStackTrace();
} finally {
}
return flag;
}
/**
* 删除文件夹
* @param directoryName
* @throws IOException
*/
public static void removeDirectory(String pathName) throws IOException{
try {
if (pathName.startsWith("/") && pathName.endsWith("/")) {
String newPathName = new String(pathName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
//更换目录到当前目录
String beforePath = "";
ftp.changeWorkingDirectory("/");
ftp.changeWorkingDirectory(newPathName);
FTPFile[] files = ftp.listFiles();
if(files.length >0){
for (FTPFile file : files) {
if (file.isFile()) {
deleteFile(pathName , file.getName());
} else if (file.isDirectory()) {
if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
ftp.changeWorkingDirectory(new String(file.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET));
FTPFile[] fileSecond = ftp.listFiles();
if(fileSecond.length > 0){
removeDirectory(pathName + file.getName() + "/");
}else{
ftp.changeWorkingDirectory("/");
ftp.changeWorkingDirectory(newPathName);
ftp.removeDirectory(new String(file.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET));
}
}
}
}
beforePath=subStringPath(pathName);
ftp.changeWorkingDirectory("/");
ftp.changeWorkingDirectory(new String(beforePath.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
newPathName =fileNameDelete(pathName);
ftp.removeDirectory(new String(newPathName.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
}else {
beforePath=subStringPath(pathName);
ftp.changeWorkingDirectory("/");
ftp.changeWorkingDirectory(new String(beforePath.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
newPathName =fileNameDelete(pathName);
ftp.removeDirectory(new String(newPathName.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
}
}else {
if(!pathName.startsWith("/")){
pathName = "/"+pathName;
}
if(!pathName.endsWith("/")){
pathName = pathName + "/";
}
removeDirectory(pathName);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
closeFtp();
}
}
private static String subStringPath (String pathName){
if(pathName.endsWith("/")){
pathName = pathName.substring(0,pathName.length()-1);
pathName = pathName.substring(0,pathName.lastIndexOf("/"));
}else{
pathName = pathName.substring(0,pathName.lastIndexOf("/"));
}
return pathName;
}
private static String fileNameDelete(String pathName){
if(pathName.endsWith("/")){
pathName = pathName.substring(0,pathName.length()-1);
pathName = pathName.substring(pathName.lastIndexOf("/")+1,pathName.length());
}else{
pathName = pathName.substring(pathName.lastIndexOf("/"),pathName.length());
}
return pathName;
}
/**
* 上传文件进度条
*/
/**
* 上传文件到FTP服务器,支持断点续传 并返回上传文件进度
* @param local 本地文件名称,绝对路径
* @param remote 远程文件路径,使用/home/directory1/subdirectory/file.ext
* 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
* @return 上传结果
* @throws IOException
*/
public static UploadStatus upload(String local, String remote) throws Exception{
try {
if (!ftp.isConnected()) {
logger.debug("远程服务器相应目录创建失败");
}
UploadStatus result;
// 对远程目录的处理 并返回文件的名称
String remoteFileName = createDirectory(remote, ftp);
// 检查远程是否存在文件
FTPFile[] files = ftp.listFiles(remoteFileName);
File localFile = new File(local);
if(localFile.length() <=0){
logger.debug("本地文件不存在");
}
if (files.length == 1) {
//判断文件是否存在
long remoteSize = files[0].getSize();
long localSize = localFile.length();
if(remoteSize==localSize){
return UploadStatus.File_Exits;
}else if(remoteSize > localSize){
return UploadStatus.Remote_Bigger_Local;
}
result = writeByUnit(remoteFileName,localFile,ftp,remoteSize,localFile.length());
} else {
result = writeByUnit(remoteFileName,localFile,ftp,0,localFile.length());
}
return result;
}catch (IOException e){
throw e;
}finally {
//上传完成之后 切回到根目录
ftp.changeWorkingDirectory("/");
}
}
/**
* 判断目录
* @param remoteFilePath 远程服务器上面的 文件目录
* @param ftpClient ftp客户端
* @return
* @throws Exception
*/
private static String createDirectory(String remoteFilePath,FTPClient ftpClient) throws Exception {
if(ftpClient == null){
// throw new CreateException(-1,"FTP客户端为空,请先连接到客户端");
}
String fileName = remoteFilePath;
if(remoteFilePath.contains("/")){
fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/") + 1);
String directory = remoteFilePath.substring(0, remoteFilePath.lastIndexOf("/") + 1);
if(directory.startsWith("/")){
directory = directory.substring(1);
}
while (true){
if(!directory.contains("/")){
break;
}
String subDirectory = directory.substring(0, directory.indexOf("/"));
directory = directory.substring(directory.indexOf("/")+1);
if (!ftpClient.changeWorkingDirectory(subDirectory)) {
if (ftpClient.makeDirectory(subDirectory)) {
ftpClient.changeWorkingDirectory(subDirectory);
} else {
logger.debug("创建目录失败");
}
}
}
}
return fileName;
}
/**
* 上传文件到服务器,新上传和断点续传
* @param remoteFile 远程文件名,在上传之前已经将服务器工作目录做了改变
* @param localFile 本地文件File句柄,绝对路径
* @param ftpClient FTPClient引用 beginSize是指文件长传开始指针位置 endSize是结束的位置 为多线程上传下载提供接口 不过该方法还需要修改
* @return
* @throws IOException
*/
private static UploadStatus writeByUnit(String remoteFile,File localFile,FTPClient ftpClient,long beginSize,long endSize) throws Exception {
long localSize = localFile.length();
if(endSize > localSize){
endSize = localSize;
}
if(beginSize < 0){
beginSize = 0;
}
//等待写入的文件大小
long writeSize = endSize - beginSize;
if(writeSize <= 0){
logger.debug("文件指针参数出错");
}
//获取百分单位是 1-100
RandomAccessFile raf = new RandomAccessFile(localFile,"r");
OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes(LOCAL_CHARSET),SERVER_CHARSET));
//把文件指针移动到 开始位置
ftpClient.setRestartOffset(beginSize);
raf.seek(beginSize);
//定义最小移动单位是 1024字节 也就是1kb
byte[] bytes = new byte[1024];
int c;
double finishSize = 0 + beginSize;
double finishPercent = 0;
int flag = 1;
//存在一个bug 当分布移动的时候 可能会出现下载重复的问题 后期需要修改
while ((c = raf.read(bytes)) != -1) {
out.write(bytes, 0, c);
finishSize += c;
if(finishSize > endSize){
finishPercent = 1;
System.out.println(">>>>>完成进度:" + finishPercent);
// fileObserverAble.setKeyValue(localFile.getName(),finishPercent,"upload");
break;
}
String percent="";
if ((finishSize / endSize) - finishPercent > 0.01) {
finishPercent = finishSize / endSize;
percent = getPercentFormat(finishPercent,3,0);
System.out.println(">>>>>完成进度:" + percent);
// fileObserverAble.setKeyValue(localFile.getName(),finishPercent,"upload");
}else{
if(finishPercent > 0.99&&flag==1){
flag=0;
finishPercent = 1.0;
percent = getPercentFormat(finishPercent,3,0);
System.out.println(">>>>>完成进度:" + percent);
}
}
}
out.flush();
raf.close();
out.close();
boolean result =ftpClient.completePendingCommand();//当有返回流时才使用,用于手动结束方法
return result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;
}
private static String getPercentFormat(double d,int IntegerDigits,int FractionDigits){
NumberFormat nf = java.text.NumberFormat.getPercentInstance();
nf.setMaximumIntegerDigits(IntegerDigits);//小数点前保留几位
nf.setMinimumFractionDigits(FractionDigits);// 小数点后保留几位
String str = nf.format(d);
return str;
}
/**
* 从FTP服务器上下载文件
* @param remote 远程文件路径 /data/MyEclipse 2017 S2.zip
* @param local 本地文件路径 E:\\zhanghaijie\\测试\\MyEclipse 2017 S2.zip
* @return 是否成功
* @throws IOException
*/
public static boolean download(String remote,String local) throws Exception{
FTPFile[] files = ftp.listFiles(remote);
if(files == null || files.length < 0){
logger.debug("远程文件不存在");
return false;
}
if(files.length != 1){
logger.debug("远程文件不唯一");
return false;
}
File localFile = new File(local);
if(localFile.exists()){
long localBeginSize = localFile.length();
if(localBeginSize == files[0].getSize()){
logger.debug("文件已经存在");
}else if(localBeginSize > files[0].getSize()){
logger.debug("下载文件出错");
}
return downloadByUnit(remote,local,localBeginSize,files[0].getSize());
}else {
return downloadByUnit(remote,local,0,files[0].getSize());
}
}
private static Boolean downloadByUnit(String remote,String local,long beginSize,long endSize) throws Exception {
File localFile = new File(local);
long waitSize = endSize - beginSize;
//进行断点续传,并记录状态
FileOutputStream out = new FileOutputStream(localFile,true);
//把文件指针移动到 开始位置
ftp.setRestartOffset(beginSize);
InputStream in = ftp.retrieveFileStream(new String(remote.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
byte[] bytes = new byte[1024];
int c;
int flag = 1;
double finishSize =0 + beginSize;
double finishPercent = 0;
while((c = in.read(bytes))!= -1){
out.write(bytes,0,c);
finishSize += c;
if(finishSize > endSize){
//System.out.println(">>>>>完成进度:" + 1);
// fileObserverAble.setKeyValue(localFile.getName(),1,"download");
}
String percent = "";
if ((finishSize / endSize) - finishPercent > 0.01) {
finishPercent = finishSize / endSize;
percent = getPercentFormat(finishPercent,3,0);
System.out.println(">>>>>完成进度:" + percent);
// fileObserverAble.setKeyValue(localFile.getName(),finishPercent,"upload");
}else{
if(finishPercent > 0.99&&flag==1){
flag=0;
finishPercent = 1.0;
percent = getPercentFormat(finishPercent,3,0);
System.out.println(">>>>>完成进度:" + percent);
}
}
}
in.close();
out.close();
return ftp.completePendingCommand();
}
/**
* 判断ftp服务器上该目录下是否文件存在
* @throws IOException
*/
public static boolean checkFileIsExist(String pathName,String fileName) throws SwordBaseCheckedException, IOException{
boolean flag = false;
String newPathName = new String(pathName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
ftp.changeWorkingDirectory(newPathName);
// 读取文件
FTPFile[] ftpFiles = ftp.listFiles();
for (FTPFile file : ftpFiles) {
if (fileName.equalsIgnoreCase(file.getName())) {
flag = true;
}
}
return flag;
}
}