1、ftp 服务器信息实体类:
public class FTPServerBean {
/**
* 服务器地址
*/
private String hostname;
/**
* 端口
*/
private int port;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 获取服务器地址
* @return hostname 返回服务器地址
*/
public String getHostname() {
return hostname;
}
/**
* @param hostname 服务器地址
*/
public void setHostname(String hostname) {
this.hostname = hostname;
}
/**
* 获取服务器端口
* @return port 返回服务器端口
*/
public int getPort() {
return port;
}
/**
* @param port 服务器端口
*/
public void setPort(int port) {
this.port = port;
}
/**
* 获取服务器用户名
* @return username 返回服务器用户名
*/
public String getUsername() {
return username;
}
/**
* @param username 服务器用户名
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取服务器密码
* @return password
*/
public String getPassword() {
return password;
}
/**
* @param password 服务器密码
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 构造函数
* @param hostname 服务器地址
* @param port 服务器端口
* @param username 服务器用户名
* @param password 服务器密码
*/
public FTPServerBean(String hostname, int port, String username, String password)
{
this.hostname = hostname;
this.port = port;
this.username = username;
this.password = password;
}
}
2、文件上传类:
public class FTPUpload {
/*** ftpClient
*/
private FTPClient ftpClient = null;
/**
* ftp 的配置信息
*/
private FTPServerBean ftpBean = null;
/**
*
* @param ftpBean
*/
public FTPUpload() {
this.ftpBean = getFTPBean();
this.ftpClient = getClient();
}
/**
* 日志
*/
private static final Logger LOG = Logger.getLogger(FTPUpload.class);
/**
* ftp 登陆
* @return isLogin
*/
public boolean ftpLogin() {
boolean isLogin = false;
try {
if (this.ftpBean.getPort() > 0) {
this.ftpClient.connect(this.ftpBean.getHostname(), ftpBean.getPort()); // 连接服务器
} else {
this.ftpClient.connect(this.ftpBean.getHostname());
}
// FTP服务器连接回答
int reply = this.ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
this.ftpClient.disconnect();
return isLogin;
}
ftpClient.setControlEncoding("GBK");
// conf 设置服务器的编码
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");
this.ftpClient.login(this.ftpBean.getUsername(), this.ftpBean.getPassword()); // 登陆服务器
// 设置传输协议
this.ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
isLogin = true;
} catch (Exception e) {
LOG.error("登陆 ftp 服务器失败 " + e.getMessage(), e);
return false;
}
return isLogin;
}
/**
* ftp 关闭连接
*/
public void ftpLogOut() {
if (null != this.ftpClient && this.ftpClient.isConnected()) {
try {
this.ftpClient.logout(); // 退出FTP服务器
} catch (IOException e) {
LOG.error("退出 ftp 服务器失败 " + e.getMessage(), e);
} finally {
try {
this.ftpClient.disconnect(); // 关闭连接
} catch (IOException e) {
LOG.error("断开 ftp 连接失败 " + e.getMessage(), e);
e.printStackTrace();
}
}
}
}
/**
* ftp 上传
* @param localPath 本地文件路径
* @param remotePath 远程文件路径
* @return result 返回上传是否失败
*/
public boolean upload(String localPath, String remotePath) {
if(!ftpLogin()){
LOG.error("ftp 登陆失败");
return false;
}
// 创建目录
if(!createDirs(remotePath.substring(0, remotePath.lastIndexOf('/') ))){
LOG.error("ftp 远程创建目录失败,已终止文件上传");
}
boolean result = false;
FTPFile[] files = null;
try {
files = ftpClient.listFiles(new String(remotePath.getBytes("utf-8"), "iso-8859-1"));
} catch (IOException e) {
LOG.error("列举指定路径的文件失败" + e.getMessage(), e);
return false;
}
// 如果远程文件已存在
if(files.length == 1){
long remoteSize = files[0].getSize();
File f = null;
f = new File(localPath);
long localSize = f.length();
if(remoteSize == localSize){ // 通过远程文件大小和名称来判断是否存在(不太科学,可用 MD5 来判断)
LOG.error("远程文件已存在");
return false;
}else if(remoteSize > localSize){
LOG.error("远程文件大于本地文件");
return false;
}
// 移动文件内读取指针,实现断点续传
result = uploadFile(remotePath, f, remoteSize);
// 如果断点续传没有成功,则删除服务器上文件,重新上传
if(!result){
try {
ftpClient.deleteFile(new String(remotePath.getBytes("utf-8"), "iso-8859-1"));
} catch (IOException e) {
LOG.error("重新上传,删除远程文件失败" + e.getMessage(), e);
return false;
}
result = uploadFile(remotePath, f, 0);
}
}
// 如果远程文件不存在
else {
result = uploadFile(remotePath, new File(localPath), 0);
}
ftpLogOut();
return result;
}
/**
* 上传文件
* @param remotePath 远程文件目录
* @param localPath 本地文件目录
* @param remoteSize 远程文件大小(若远程的文件名已存在)
* @return result 返回上传是否成功
*/
@SuppressWarnings("resource")
public boolean uploadFile(String remotePath, File localPath, long remoteSize){
boolean result = false;
long step = localPath.length();
long process = 0L;
long localreadbytes = 0L;
RandomAccessFile raf;
try {
raf = new RandomAccessFile(localPath, "r");
} catch (FileNotFoundException e) {
LOG.error("本地文件不存在" + e.getMessage(), e);
return false;
}
OutputStream out = null;
try {
out = ftpClient.appendFileStream(new String(remotePath.getBytes("utf-8"), "iso-8859-1"));
if(out == null)
{
LOG.error("输出流对象为空");
return false;
}
} catch (UnsupportedEncodingException e) {
LOG.error("转码失败" + e.getMessage(), e);
return false;
} catch (IOException e) {
LOG.error("获取输出流失败", e);
}
//文件上传
if(remoteSize > 0){
ftpClient.setRestartOffset(remoteSize);
process = remoteSize * 100 /step;
try {
raf.seek(remoteSize);
} catch (IOException e) {
LOG.error("文件指针移动失败" + e.getMessage(), e);
return false;
}
localreadbytes = remoteSize;
}
byte[] bytes = new byte[1024];
int c;
try {
while((c = raf.read(bytes))!= -1){
out.write(bytes, 0, c);
localreadbytes += c;
if(localreadbytes * 100 / step != process){
process = localreadbytes * 100 / step;
/**
* 可显示上传进度...
*/
}
}
out.flush();
raf.close();
out.close();
result =ftpClient.completePendingCommand();
} catch (IOException e) {
LOG.error("上传文件失败" + e.getMessage(), e);
}
return result;
}
/**
* ftpClient
* @return
*/
private FTPClient getClient(){
if(null == ftpBean)
ftpBean = this.getFTPBean();
return new FTPClient();
}
/**
* 获取 ftpBean
* @return ftpBean
*/
public FTPServerBean getFTPBean() {
// 初始化 ftp 服务器的信息
String ip = "127.0.0.1";
String username = "admin";
String password = "admin";
int port = 0;
ftpBean = new FTPServerBean(ip, port, username, password);
return ftpBean;
}
/**
* 在服务器上创建目录
* @param remotePath 远程路径,用于创建远程目录
*/
public boolean createDirs(String remotePath){
String[] dirs = remotePath.split("/");
for(String dir : dirs){
try {
// 如果创建目录失败
String currentDir = new String(dir.getBytes("utf-8"), "iso-8859-1");
if(!(ftpClient.makeDirectory(currentDir) && ftpClient.changeWorkingDirectory(currentDir))){
LOG.error("ftp 远程目录创建失败");
return false;
}
} catch (IOException e) {
LOG.error("远程目录创建失败" + e.getMessage(), e);
}
}
return true;
}
}