主要使用apache中的net包來實現。網址http://commons.apache.org/net/。具體包的下載和API文檔請看官網。
斷點上傳就是在上傳的過程中設置傳輸的起始位置。並設置二進制傳輸。
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.PrintWriter;
import org.apache.commons.net.PrintCommandListener;
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 ContinueFTP {
private FTPClient ftpClient = new FTPClient();
public ContinueFTP(){
//設置將過程中使用到的命令輸出到控制檯
this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
}
/**
* 連接到FTP服務器
* @param hostname 主機名
* @param port 端口
* @param username 用戶名
* @param password 密碼
* @return 是否連接成功
* @throws IOException
*/
public boolean connect(String hostname,int port,String username,String password) throws IOException{
ftpClient.connect(hostname, port);
if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
if(ftpClient.login(username, password)){
return true;
}
}
disconnect();
return false;
}
/**
* 從FTP服務器上下載文件
* @param remote 遠程文件路徑
* @param local 本地文件路徑
* @return 是否成功
* @throws IOException
*/
public boolean download(String remote,String local) throws IOException{
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
boolean result;
File f = new File(local);
FTPFile[] files = ftpClient.listFiles(remote);
if(files.length != 1){
System.out.println("遠程文件不唯一");
return false;
}
long lRemoteSize = files[0].getSize();
if(f.exists()){
OutputStream out = new FileOutputStream(f,true);
System.out.println("本地文件大小爲:"+f.length());
if(f.length() >= lRemoteSize){
System.out.println("本地文件大小大於遠程文件大小,下載中止");
return false;
}
ftpClient.setRestartOffset(f.length());
result = ftpClient.retrieveFile(remote, out);
out.close();
}else {
OutputStream out = new FileOutputStream(f);
result = ftpClient.retrieveFile(remote, out);
out.close();
}
return result;
}
/**
* 上傳文件到FTP服務器,支持斷點續傳
* @param local 本地文件名稱,絕對路徑
* @param remote 遠程文件路徑,使用/home/directory1/subdirectory/file.ext 按照Linux上的路徑指定方式,支持多級目錄嵌套,支持遞歸創建不存在的目錄結構
* @return 上傳結果
* @throws IOException
*/
public UploadStatus upload(String local,String remote) throws IOException{
//設置PassiveMode傳輸
ftpClient.enterLocalPassiveMode();
//設置以二進制流的方式傳輸
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
UploadStatus result;
//對遠程目錄的處理
String remoteFileName = remote;
if(remote.contains("/")){
remoteFileName = remote.substring(remote.lastIndexOf("/")+1);
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 = remote.substring(start,end);
if(!ftpClient.changeWorkingDirectory(subDirectory)){
if(ftpClient.makeDirectory(subDirectory)){
ftpClient.changeWorkingDirectory(subDirectory);
}else {
System.out.println("創建目錄失敗");
return UploadStatus.Create_Directory_Fail;
}
}
start = end + 1;
end = directory.indexOf("/",start);
//檢查所有目錄是否創建完畢
if(end <= start){
break;
}
}
}
}
//檢查遠程是否存在文件
FTPFile[] files = ftpClient.listFiles(remoteFileName);
if(files.length == 1){
long remoteSize = files[0].getSize();
File f = new File(local);
long localSize = f.length();
if(remoteSize==localSize){
return UploadStatus.File_Exits;
}else if(remoteSize > localSize){
return UploadStatus.Remote_Bigger_Local;
}
//嘗試移動文件內讀取指針,實現斷點續傳
InputStream is = new FileInputStream(f);
if(is.skip(remoteSize)==remoteSize){
ftpClient.setRestartOffset(remoteSize);
if(ftpClient.storeFile(remote, is)){
return UploadStatus.Upload_From_Break_Success;
}
}
//如果斷點續傳沒有成功,則刪除服務器上文件,重新上傳
if(!ftpClient.deleteFile(remoteFileName)){
return UploadStatus.Delete_Remote_Faild;
}
is = new FileInputStream(f);
if(ftpClient.storeFile(remote, is)){
result = UploadStatus.Upload_New_File_Success;
}else{
result = UploadStatus.Upload_New_File_Failed;
}
is.close();
}else {
InputStream is = new FileInputStream(local);
if(ftpClient.storeFile(remoteFileName, is)){
result = UploadStatus.Upload_New_File_Success;
}else{
result = UploadStatus.Upload_New_File_Failed;
}
is.close();
}
return result;
}
/**
* 斷開與遠程服務器的連接
* @throws IOException
*/
public void disconnect() throws IOException{
if(ftpClient.isConnected()){
ftpClient.disconnect();
}
}
public static void main(String[] args) {
ContinueFTP myFtp = new ContinueFTP();
try {
myFtp.connect("192.168.21.171", 21, "test", "test");
System.out.println(myFtp.upload("E://VP6.flv", "/MIS/video/VP6.flv"));
myFtp.disconnect();
} catch (IOException e) {
System.out.println("連接FTP出錯:"+e.getMessage());
}
}
}