断点上传和下载工具类,包括目录文件的创建、判断、ftp连接等,直接copy就可用。使用FileZilla Server,需要用commons.net的jar包,到官网下载。最大的坑就是编码问题,在window默认GBK,ftp Server从09.41后默认utf-8,百度一大堆,自行查找。最佳的解决在此文章ftpConnect()方法中,请阅读。
package com.utils;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
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.net.SocketException;
import java.util.HashMap;
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;
public class FtpUtils {
private static FTPClient ftpClient = new FTPClient();
private static String encoding = System.getProperty("file.encoding");
private static HashMap<String, String> map;
private static String directory;
/**
* 创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
*
* @param remote
* @return
* @throws IOException
*/
public static ResponseResult CreateDirecroty(String remote, String filename)
throws IOException {
ResponseResult checkRemoteFile;
checkRemote(remote);
// 如果远程目录不存在,则递归创建远程服务器目录
if (!directory.equalsIgnoreCase("/")
&& !changeWorkingDirectory(new String(directory), ftpClient)) {
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf("/", start);
String path = "";
String paths = "";
while (true) {
// 对目录进行转码
String subDirectory = new String(remote.substring(start, end)
.getBytes(encoding), "iso-8859-1");
path = path + "/" + subDirectory;
checkRemoteFile = checkRemoteFile(filename, ftpClient);
if (checkRemoteFile.getStatus() != 200) {
if (makeDirectory(subDirectory, ftpClient)) {
changeWorkingDirectory(subDirectory, ftpClient);
} else {
System.out.println("创建目录[" + subDirectory + "]失败");
changeWorkingDirectory(subDirectory, ftpClient);
}
} else {
changeWorkingDirectory(subDirectory, ftpClient);
}
paths = paths + "/" + subDirectory;
start = end + 1;
end = directory.indexOf("/", start);
// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
} else {
// 检查服务器文件是否存在
checkRemoteFile = checkRemoteFile(filename, ftpClient);
}
return checkRemoteFile;
}
private static void checkRemote(String remote) {
char c = remote.charAt(remote.length() - 1);
if ("/".charAt(0) == c) {
directory = remote;
} else {
directory = remote + "/";
}
}
/**
* 创建目录
*
* @param dir
* @param ftp
* @return
*/
public static boolean makeDirectory(String dir, FTPClient ftp) {
boolean flag = true;
try {
flag = ftp.makeDirectory(dir);
if (flag) {
System.out.println("创建文件夹" + dir + " 成功!");
} else {
System.out.println("创建文件夹" + dir + " 失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 判断ftp服务器文件是否存在
*
* @param filename
* @param ftp
* @return
* @throws IOException
*/
public static ResponseResult checkRemoteFile(String filename, FTPClient ftp)
throws IOException {
FTPFile[] ftpFileArr = ftp.listFiles(filename);
for (FTPFile ftpFile : ftpFileArr) {
if (ftpFileArr.length > 0) {
System.out.println(ftpFile.getSize());
return ResponseResult.build(200, "存在");
}
}
return ResponseResult.build(300, "不存在");
}
/**
* 改变目录路径
*
* @param directory
* @param ftp
* @return
*/
public static boolean changeWorkingDirectory(String directory, FTPClient ftp) {
boolean flag = true;
try {
flag = ftp.changeWorkingDirectory(directory);
if (flag) {
System.out.println("进入文件夹" + directory + " 成功!");
} else {
System.out.println("进入文件夹" + directory + " 失败!");
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return flag;
}
/**
* 检查本地文件是否存在
*
* @param localPath
* 本地文件路径
* @return
*/
public static long checkLocalFile(String localPath) {
File file = new File(localPath);
if (file.exists()) {
return file.length();
}
return 0;
}
/**
* Description: 从FTP服务器下载文件
*
* @param url
* FTP服务器hostname
* @param port
* FTP服务器端口
* @param username
* FTP登录账号
* @param password
* FTP登录密码
* @param remotePath
* FTP服务器上的相对路径
* @param fileName
* 下载的文件名
* @param localPath
* 下载后保存到本地的路径
* @return
*/
public static boolean downloadFile(String fileName, String localPath) {
boolean status = false;
try {
ftpConnect();
// 转移到FTP服务器目录至指定的目录下
ftpClient.changeWorkingDirectory(new String(map.get("remotePath")
.getBytes(encoding), "iso-8859-1"));
// 获取本地文件大小
long checkLocalFile = checkLocalFile(localPath + "/" + fileName);
// 获取远程文件
String remotePathFile = map.get("remotePath") + "/" + fileName;
FTPFile[] fs = ftpClient.listFiles(new String(remotePathFile
.getBytes(encoding), "iso-8859-1"));
// 判断本地文件是否存在
if (checkLocalFile != 0) {
System.out.println("本地文件已存在");
// 存在,则进行断点下载
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
checkLocalFile = downBreakPoint(localPath,
checkLocalFile, ff);
}
status = true;
}
} else {
// 直接下载
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
File localFile = new File(localPath + "/"
+ ff.getName());
OutputStream out = new FileOutputStream(localFile);
ftpClient.retrieveFile(ff.getName(), out);
}
}
ftpClient.completePendingCommand();
status = true;
}
ftpClient.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException ioe) {
}
}
}
return status;
}
/**
* 断点下载代码段
* @param localPath
* @param checkLocalFile
* @param ff
* @return
* @throws FileNotFoundException
* @throws IOException
* @throws UnsupportedEncodingException
*/
private static long downBreakPoint(String localPath, long checkLocalFile,
FTPFile ff) throws FileNotFoundException, IOException,
UnsupportedEncodingException {
// 获得远程文件大小
long RemoteSize = ff.getSize();
if (RemoteSize <= checkLocalFile) {
System.out.println("文件已下载");
} else {
// 断点下载
File localFile = new File(localPath + "/" + ff.getName());
OutputStream out = new FileOutputStream(localFile);
InputStream in = ftpClient.retrieveFileStream(((new String(ff
.getName().getBytes(encoding), "iso-8859-1"))));
ftpClient.setRestartOffset(checkLocalFile);
byte[] bytes = new byte[1024];
// long step = RemoteSize / 100;
// long process = checkLocalFile / step;
int c;
while ((c = in.read(bytes)) != -1) {
out.write(bytes, 0, c);
checkLocalFile += c;
// long nowProcess = checkLocalFile /
// step;
/*
* if (nowProcess > process) { process = nowProcess; if (process
* % 10 == 0) System.out.println("下载进度:" + process); //
* 更新文件下载进度,值存放在process变量中 }
*/
}
in.close();
out.close();
ftpClient.completePendingCommand();
}
return checkLocalFile;
}
/**
* 断点续传
*
* @param processStep
* 需要显示的处理进度步进值
* @param url
* 地址
* @param port
* 端口
* @param username
* 用户名
* @param password
* 密码
* @param remotePath
* 远程路径
* @param filename
* 本地上传的文件名
* @param file
* 绝对路径
* @return
* @throws IOException
*/
public static boolean uploadFileBreakPoint(String filename, File file) {
boolean status = false;
try {
ftpConnect();
// 转移目录到远端服务器目录
ftpClient.changeWorkingDirectory(map.get("remotePath"));
String f = new String(filename.getBytes(encoding), "iso-8859-1");
// 检查ftp服务器中目录否已存在
ResponseResult result = CreateDirecroty(map.get("remotePath"), f);
// 文件存在,判断文件大小进行选择上传
if (result.getStatus() == 200) {
System.out.println("文件已存在");
// 1.服务器文件大于将要上传文件,不需要上传,或者重新上传
FTPFile[] listFiles = ftpClient.listFiles(map.get("remotePath")
+ "/" + f);
System.out.println(file.length());
if (listFiles[0].getSize() >= file.length()) {
System.out.println("不需要上传");
return true;
} else {
status = resumeBreakPoint(filename, file, listFiles);
}
}
ftpClient.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return status;
}
/**
* 上传文件
* @param fileName
* @param file
* @return
* @throws FileNotFoundException
* @throws IOException
* @throws UnsupportedEncodingException
*/
public static boolean uploadFile(String fileName, File file)
throws FileNotFoundException, IOException,
UnsupportedEncodingException {
boolean status = false;
ftpConnect();
ftpClient.changeWorkingDirectory(map.get("remotePath"));
// String f = new String(fileName.getBytes(encoding), "iso-8859-1");
BufferedInputStream inputStream = new BufferedInputStream(
new FileInputStream(file));
status = ftpClient.storeFile(new String(fileName.getBytes(encoding),
"iso-8859-1"), inputStream);
if (status) {
System.out.println("上传成功!");
}
return status;
}
/**
* 断点上传代码段
*
* @param filename
* @param file
* @param listFiles
* @return
* @throws FileNotFoundException
* @throws IOException
* @throws UnsupportedEncodingException
*/
private static boolean resumeBreakPoint(String filename, File file,
FTPFile[] listFiles) throws FileNotFoundException, IOException,
UnsupportedEncodingException {
boolean status;
// 2.服务器文件小于将要上传文件,进行断点续传
// 显示进度的上传
// long step = file.length() / 10;
// long process = 0;
long localreadbytes = 0L;
RandomAccessFile raf = new RandomAccessFile(file, "rw");
OutputStream out = ftpClient.appendFileStream(new String(filename
.getBytes(encoding), "iso-8859-1"));
// 断点续传
ftpClient.setRestartOffset(listFiles[0].getSize());
// process = listFiles[0].getSize() % step;
raf.seek(listFiles[0].getSize());
localreadbytes = listFiles[0].getSize();
byte[] bytes = new byte[1024];
int c;
while ((c = raf.read(bytes)) != -1) {
out.write(bytes, 0, c);
localreadbytes += c;
/*
* if (localreadbytes / step != process) { process = localreadbytes
* / step; System.out.println("上传进度:" + process); }
*/
}
out.flush();
raf.close();
out.close();
boolean result = ftpClient.completePendingCommand();
if (listFiles[0].getSize() > 0) {
status = result ? true : false;
} else {
status = result ? true : false;
}
return status;
}
/**
* ftp连接
* @return
* @throws SocketException
* @throws IOException
*/
private static boolean ftpConnect() throws SocketException, IOException {
map = LoadProperties.GetAllProperties("ftp.properties");
boolean status = false;
ftpClient.connect(map.get("ftp_url"), Integer.valueOf(map.get("port")));// 连接FTP服务器
// 登录
ftpClient.login(map.get("username"), map.get("password"));
// *************
if (ftpClient.login(map.get("username"), map.get("password"))) {
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
"OPTS UTF8", "ON"))) {
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
encoding = "UTF-8";
} else {
ftpClient.setControlEncoding(encoding);
}
System.out.println(encoding);
ftpClient.enterLocalPassiveMode();
ftpClient.setBufferSize(1024 * 1024 * 2);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
status = true;
} else {
ftpClient.disconnect();
status = false;
System.out.println("连接失败");
}
// *************
return status;
}
/**
* 在FTP服务器下载文件到本地
*/
public void testDownFile() {
try {
boolean flag = downloadFile("7.txt",
"C:\\Users\\Administrator\\Desktop");
System.out.println(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将本地文件上传到FTP服务器
*/
public void testUpLoadFromDisk() {
try {
File file = new File(
"C:/Users/Public/Videos/Sample Videos/3 - 副本.mp4/");
boolean flag;
// flag = uploadFileBreakPoint("3 - 副本.mp4", file);
flag = uploadFile("3 - 副本.mp4", file);
System.out.println(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
// FtpUtils fa = new FtpUtils();
//// fa.testDownFile();
// fa.testUpLoadFromDisk();
}
}
欢迎大家指正。