添加 apache.commons.NET.ftp
包
- package com.ftp;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.io.RandomAccessFile;
- 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;
- import org.junit.Test;
- /** *//**
- * 支持斷點續傳的FTP實用類
- * @version 0.1 實現基本斷點上傳下載
- * @version 0.2 實現上傳下載進度彙報
- * @version 0.3 實現中文目錄創建及中文文件創建,添加對於中文的支持
- */
- public class ContinueFTP2 implements Runnable{
- //枚舉類UploadStatus代碼
- public enum UploadStatus {
- Create_Directory_Fail, //遠程服務器相應目錄創建失敗
- Create_Directory_Success, //遠程服務器闖將目錄成功
- Upload_New_File_Success, //上傳新文件成功
- Upload_New_File_Failed, //上傳新文件失敗
- File_Exits, //文件已經存在
- Remote_Bigger_Local, //遠程文件大於本地文件
- Upload_From_Break_Success, //斷點續傳成功
- Upload_From_Break_Failed, //斷點續傳失敗
- Delete_Remote_Faild; //刪除遠程文件失敗
- }
- //枚舉類DownloadStatus代碼
- public enum DownloadStatus {
- Remote_File_Noexist, //遠程文件不存在
- Local_Bigger_Remote, //本地文件大於遠程文件
- Download_From_Break_Success, //斷點下載文件成功
- Download_From_Break_Failed, //斷點下載文件失敗
- Download_New_Success, //全新下載文件成功
- Download_New_Failed; //全新下載文件失敗
- }
- public FTPClient ftpClient = new FTPClient();
- private String ftpURL,username,pwd,ftpport,file1,file2;
- public ContinueFTP2(String _ftpURL,String _username,String _pwd,String _ftpport,String _file1,String _file2 ){
- //設置將過程中使用到的命令輸出到控制檯
- ftpURL = _ftpURL;
- username = _username;
- pwd = _pwd;
- ftpport = _ftpport;
- file1 = _file1;
- file2 = _file2;
- 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);
- ftpClient.setControlEncoding("GBK");
- if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
- if(ftpClient.login(username, password)){
- return true;
- }
- }
- disconnect();
- return false;
- }
- /** *//**
- * 從FTP服務器上下載文件,支持斷點續傳,上傳百分比彙報
- * @param remote 遠程文件路徑
- * @param local 本地文件路徑
- * @return 上傳的狀態
- * @throws IOException
- */
- public DownloadStatus download(String remote,String local) throws IOException{
- //設置被動模式
- ftpClient.enterLocalPassiveMode();
- //設置以二進制方式傳輸
- ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
- DownloadStatus result;
- //檢查遠程文件是否存在
- FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));
- if(files.length != 1){
- System.out.println("遠程文件不存在");
- return DownloadStatus.Remote_File_Noexist;
- }
- long lRemoteSize = files[0].getSize();
- File f = new File(local);
- //本地存在文件,進行斷點下載
- if(f.exists()){
- long localSize = f.length();
- //判斷本地文件大小是否大於遠程文件大小
- if(localSize >= lRemoteSize){
- System.out.println("本地文件大於遠程文件,下載中止");
- return DownloadStatus.Local_Bigger_Remote;
- }
- //進行斷點續傳,並記錄狀態
- FileOutputStream out = new FileOutputStream(f,true);
- ftpClient.setRestartOffset(localSize);
- InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));
- byte[] bytes = new byte[1024];
- long step = lRemoteSize /100;
- long process=localSize /step;
- int c;
- while((c = in.read(bytes))!= -1){
- out.write(bytes,0,c);
- localSize+=c;
- long nowProcess = localSize /step;
- if(nowProcess > process){
- process = nowProcess;
- if(process % 10 == 0)
- System.out.println("下載進度:"+process);
- //TODO 更新文件下載進度,值存放在process變量中
- }
- }
- in.close();
- out.close();
- boolean isDo = ftpClient.completePendingCommand();
- if(isDo){
- result = DownloadStatus.Download_From_Break_Success;
- }else {
- result = DownloadStatus.Download_From_Break_Failed;
- }
- }else {
- OutputStream out = new FileOutputStream(f);
- InputStream in= ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));
- byte[] bytes = new byte[1024];
- long step = lRemoteSize /100;
- long process=0;
- long localSize = 0L;
- int c;
- while((c = in.read(bytes))!= -1){
- out.write(bytes, 0, c);
- localSize+=c;
- long nowProcess = localSize /step;
- if(nowProcess > process){
- process = nowProcess;
- if(process % 10 == 0)
- System.out.println("下載進度:"+process);
- //TODO 更新文件下載進度,值存放在process變量中
- }
- }
- in.close();
- out.close();
- boolean upNewStatus = ftpClient.completePendingCommand();
- if(upNewStatus){
- result = DownloadStatus.Download_New_Success;
- }else {
- result = DownloadStatus.Download_New_Failed;
- }
- }
- return result;
- }
- /** *//**
- * 上傳文件到FTP服務器,支持斷點續傳
- * @param local 本地文件名稱,絕對路徑
- * @param remote 遠程文件路徑,使用/home/directory1/subdirectory/file.ext或是 http://www.guihua.org /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);
- ftpClient.setControlEncoding("GBK");
- UploadStatus result;
- //對遠程目錄的處理
- String remoteFileName = remote;
- if(remote.contains("/")){
- remoteFileName = remote.substring(remote.lastIndexOf("/")+1);
- //創建服務器遠程目錄結構,創建失敗直接返回
- if(CreateDirecroty(remote, ftpClient)==UploadStatus.Create_Directory_Fail){
- return UploadStatus.Create_Directory_Fail;
- }
- }
- //檢查遠程是否存在文件
- FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));
- 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;
- }
- //嘗試移動文件內讀取指針,實現斷點續傳
- result = uploadFile(remoteFileName, f, ftpClient, remoteSize);
- //如果斷點續傳沒有成功,則刪除服務器上文件,重新上傳
- if(result == UploadStatus.Upload_From_Break_Failed){
- if(!ftpClient.deleteFile(remoteFileName)){
- return UploadStatus.Delete_Remote_Faild;
- }
- result = uploadFile(remoteFileName, f, ftpClient, 0);
- }
- }else {
- result = uploadFile(remoteFileName, new File(local), ftpClient, 0);
- }
- return result;
- }
- /** *//**
- * 斷開與遠程服務器的連接
- * @throws IOException
- */
- public void disconnect() throws IOException{
- if(ftpClient.isConnected()){
- ftpClient.disconnect();
- }
- }
- /** *//**
- * 遞歸創建遠程服務器目錄
- * @param remote 遠程服務器文件絕對路徑
- * @param ftpClient FTPClient 對象
- * @return 目錄創建是否成功
- * @throws IOException
- */
- public UploadStatus CreateDirecroty(String remote,FTPClient ftpClient) throws IOException{
- UploadStatus status = UploadStatus.Create_Directory_Success;
- String directory = remote.substring(0,remote.lastIndexOf("/")+1);
- if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){
- //如果遠程目錄不存在,則遞歸創建遠程服務器目錄
- 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("GBK"),"iso-8859-1");
- 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;
- }
- }
- }
- return status;
- }
- /** *//**
- * 上傳文件到服務器,新上傳和斷點續傳
- * @param remoteFile 遠程文件名,在上傳之前已經將服務器工作目錄做了改變
- * @param localFile 本地文件 File句柄,絕對路徑
- * @param processStep 需要顯示的處理進度步進值
- * @param ftpClient FTPClient 引用
- * @return
- * @throws IOException
- */
- public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{
- UploadStatus 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("GBK"),"iso-8859-1"));
- //斷點續傳
- if(remoteSize>0){
- ftpClient.setRestartOffset(remoteSize);
- process = remoteSize /step;
- raf.seek(remoteSize);
- localreadbytes = remoteSize;
- }
- 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);
- //TODO 彙報上傳狀態
- }
- }
- out.flush();
- raf.close();
- out.close();
- boolean result =ftpClient.completePendingCommand();
- if(remoteSize > 0){
- status = result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;
- }else {
- status = result?UploadStatus.Upload_New_File_Success:UploadStatus.Upload_New_File_Failed;
- }
- return status;
- }
- @Test
- public void run() {
- // TODO Auto-generated method stub
- try {
- this.connect(ftpURL, new java.lang.Integer(ftpport), username, pwd);
- // myFtp.ftpClient.makeDirectory(new String(" 電視劇".getBytes("GBK"),"iso-8859-1"));
- // myFtp.ftpClient.changeWorkingDirectory(new String(" 電視劇".getBytes("GBK"),"iso-8859-1"));
- // myFtp.ftpClient.makeDirectory(new String(" 走西口".getBytes("GBK"),"iso-8859-1"));
- // System.out.println(myFtp.upload("http://www.5a520.cn /yw.flv", "/yw.flv",5));
- // System.out.println(myFtp.upload("http://www.5a520.cn /走西口24.mp4","/央視走西口/新浪網/走西口 24.mp4"));
- // System.out.println(myFtp.download("/ 央視走西口/新浪網/走西口24.mp4", "E:\\走西口242.mp4"));
- this.download(file1, file2);
- // System.out.println(myFtp.upload("c:\\a.iso", "/a.iso"));
- this.disconnect();
- } catch (IOException e) {
- System.out.println("連接FTP出錯:"+e.getMessage());
- }
- }
- }