FTP断点续传



import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

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 org.apache.log4j.Logger;

public class FTPUtil {

private static FTPClient ftpClient = new FTPClient();

private static Logger logger = Logger.getLogger(FTPUtil.class);

private static String encode_charset = "UTF-8";

private final static int CACHE_SIZE = 8*1024*1024;

private final static String DIRECTORY_CREATE_FAILED = "目录创建失败";

private final static String DIRECTORY_CREATE_SUCCESS = "目录创建成功";

private final static String UPLOAD_NEW_SUCCESS = "上传文件成功";

private final static String UPLOAD_NEW_FAILED = "上传文件失败";

private final static String UPLOAD_RESUME_SUCCESS = "断点续传成功";

private final static String UPLOAD_RESUME_FAILED = "断点续传失败";

private final static String FILE_EXISTS = "文件已存在 ";

private final static String FILE_DOES_NOT_MATCH = "文件不匹配";

/**
*
* @param ftpClient FTPClient
* @param localFile 本地文件路径
* @return 上传文件路径 (ftp://ip/dir/.../file.ext)
*/
public static String upload(FTPClient ftpClient,String localFile) {
try {
File file = new File(localFile);
ftpClient.enterLocalPassiveMode();// 设置PassiveMode传输
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 设置以二进制流的方式传输
ftpClient.setControlEncoding(encode_charset);// 设置编码格式

String fileName = new String(file.getName().getBytes(encode_charset), encode_charset);//防止文件名乱码
String dateDir = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String remoteFileName = "/" + dateDir + "/" + fileName;

// 检测目标路径是否存在
if (createDirecroty(ftpClient, remoteFileName) == DIRECTORY_CREATE_FAILED) {
logger.error(DIRECTORY_CREATE_FAILED);
return null;
}
String result = null;
FTPFile[] ftpFiles = ftpClient.listFiles("/" + dateDir);
logger.debug("上传后返回的文件名"+remoteFileName);
if(ftpFiles != null && ftpFiles.length >0){
for (FTPFile ftpFile : ftpFiles) {
// 若存在相同文件名文件,则判断是否进行断点续传
if(ftpFile.getName().equals(fileName)){
long remoteSize = ftpFile.getSize();
long localSize = file.length();
if (remoteSize == localSize) {
logger.error(FILE_EXISTS);
return null;
} else if (remoteSize > localSize) {
logger.error(FILE_DOES_NOT_MATCH);
return null;
}
// 尝试移动文件内读取指针,实现断点续传
result = uploadFile(remoteFileName, file,
ftpClient, remoteSize);
logger.debug("上传结果:" + result);
if(result.equals(UPLOAD_NEW_SUCCESS) || result.equals(UPLOAD_RESUME_SUCCESS)){
logger.debug(UPLOAD_RESUME_SUCCESS);
return remoteFileName.substring(1);
} else {
logger.error("上传失败!!!");
return null;
}
}
}
// 重新上传
ftpClient.deleteFile(remoteFileName);
result = uploadFile(remoteFileName, file, ftpClient, 0);
logger.debug("上传结果:" + result);

if(result.equals(UPLOAD_NEW_SUCCESS) || result.equals(UPLOAD_RESUME_SUCCESS)){
logger.debug(UPLOAD_NEW_SUCCESS);
return remoteFileName.substring(1);
} else {
logger.error("上传失败!!!");
return null;
}
} else {
// 重新上传
ftpClient.deleteFile(remoteFileName);
result = uploadFile( remoteFileName, file, ftpClient, 0);
logger.debug("上传结果:" + result);
if(result.equals(UPLOAD_NEW_SUCCESS) || result.equals(UPLOAD_RESUME_SUCCESS)){
logger.debug(UPLOAD_NEW_SUCCESS);
return remoteFileName.substring(1);
} else {
logger.error("上传失败!!!");
return null;
}
}

} catch (FileNotFoundException e) {
logger.error("文件不存在:" + e);
return null;
} catch (UnsupportedEncodingException e) {
logger.error("编码格式不支持:" + e);
return null;
} catch (IOException e) {
logger.error("IO错误:" + e);
return null;
} finally {
closeConnections();// 关闭连接
}
}

/**
*
* @param remoteFile
* @param localFile
* @param ftpClient
* @param remoteSize
* @return
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static String uploadFile(String remoteFile,
File localFile, FTPClient ftpClient, long remoteSize)
throws IOException {
String status;
// 显示进度的上传
long step = localFile.length() / 100;
long process = 0;//百分比
long localreadbytes = 0L;
RandomAccessFile raf = new RandomAccessFile(localFile, "r");
OutputStream out = ftpClient.appendFileStream(new String(remoteFile
.getBytes(encode_charset), encode_charset));
// 断点续传
if (remoteSize > 0) {
ftpClient.setRestartOffset(remoteSize);
process = remoteSize / step;
raf.seek(remoteSize);
localreadbytes = remoteSize;
}
byte[] bytes = new byte[CACHE_SIZE];
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);
// TODO 汇报上传状态
} }
out.flush();
raf.close();
out.close();
boolean result = ftpClient.completePendingCommand();
if (remoteSize > 0) {
status = result ? UPLOAD_RESUME_SUCCESS
: UPLOAD_RESUME_FAILED;
} else {
status = result ? UPLOAD_NEW_SUCCESS : UPLOAD_NEW_FAILED;
}
return status;
}

/**
* 递归创建远程服务器目录
*
* @param remote
* @param ftpClient FTPClient
* @return status
* @throws IOException
*/
private static String createDirecroty(FTPClient ftpClient, String remote)
throws IOException {
String status = DIRECTORY_CREATE_SUCCESS;
String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) {
// 如果远程目录不存在,则递归创建远程服务器目录
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));
if (!ftpClient.changeWorkingDirectory(subDirectory)) {
if(!ftpClient.makeDirectory(subDirectory))
return DIRECTORY_CREATE_FAILED;
ftpClient.changeWorkingDirectory(subDirectory);
}
start = end + 1;
end = directory.indexOf("/", start);

// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
}
return status;
}

/**
*
* @param ftpHost 主机
* @param ftpUserName 用户名
* @param ftpPassword 密码
* @param ftpPort 端口
* @return
*/
public static FTPClient getFTPClient(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort) {
try {
ftpClient.setControlEncoding(encode_charset);
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
logger.debug("ftp参数:ftpHost=" + ftpHost + " ftpUserName="
+ ftpUserName + " ftpPassword=" + ftpPassword + " ftpPort="
+ ftpPort);
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
logger.info("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
} else {
logger.info("FTP连接成功。");
}
} catch (SocketException e) {
logger.info("FTP的IP地址可能错误,请正确配置" + e);
} catch (IOException e) {
logger.info("FTP的端口错误,请正确配置" + e);
}
return ftpClient;
}

/**
* 关闭连接
*/
private static void closeConnections() {
try {
if (ftpClient.isConnected()) {
ftpClient.disconnect();
}
} catch (IOException e) {
logger.info("关闭连接失败" + e);
}
}

public static void main(String[] args) throws IOException {
String ip = "10.3.1.190";
String username = "root";
String password = "root";

Integer port = 21;
FTPClient ftpClient = FTPUtil
.getFTPClient(ip, username, password, port);
String status = FTPUtil.upload(ftpClient,
"D:/temp/电影天堂www.dygod.net.三十极夜.中英双字.1024分辨率.rmvb");
System.out.println(status);
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值