`

JAVA中使用FTPClient上传下载资源

    博客分类:
  • java
阅读更多

最近发现apache很多jar包非常好用,刚好项目中要实现ftp上传下载功能,于是就学习了一下 apache下的一个commons net包,该包能够非常方便的编写java网络方面的程序,支持的协议也非常多,这里先发布一个用该包实现的ftp上传下 载功能!注意记得导入apache的commons net包!

 

一、利用org.apache.commons.net.ftp包实现上传下载文件资源

 

import java.io.ByteArrayInputStream;
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.UnsupportedEncodingException;

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;

public class FtpUtil {
	/**
	  * Description: 向FTP服务器上传文件
	  * @param url FTP服务器hostname
	  * @param port FTP服务器端口
	  * @param username FTP登录账号
	  * @param password FTP登录密码
	  * @param path FTP服务器保存目录
	  * @param filename 上传到FTP服务器上的文件名
	  * @param input    输入流
	  * @return 成功返回true,否则返回false
	  */
	 public boolean uploadFile(String url, int port, String username,
	   String password, String path, String filename, InputStream input) {
	  // 初始表示上传失败
	  boolean success = false;
	  // 创建FTPClient对象
	  FTPClient ftp = new FTPClient();
	  try {
	   int reply;
	   // 连接FTP服务器
	   // 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
	   ftp.connect(url, port);
	   // 登录ftp
	   ftp.login(username, password);
	   // 看返回的值是不是230,如果是,表示登陆成功
	   reply = ftp.getReplyCode();
	   // 以2开头的返回值就会为真
	   if (!FTPReply.isPositiveCompletion(reply)) {
	    ftp.disconnect();
	    return success;
	   }
	   // 转到指定上传目录
	   ftp.changeWorkingDirectory(path);
	   // 将上传文件存储到指定目录
	   ftp.storeFile(filename, input);
	   // 关闭输入流
	   input.close();
	   // 退出ftp
	   ftp.logout();
	   // 表示上传成功
	   success = true;
	  } catch (IOException e) {
	   e.printStackTrace();
	  } finally {
	   if (ftp.isConnected()) {
	    try {
	     ftp.disconnect();
	    } catch (IOException ioe) {
	    }
	   }
	  }
	  return success;
	 }  
	 
	  /**
	  * Description: 从FTP服务器下载文件
	  * @param url  FTP服务器hostname
	  * @param port   FTP服务器端口
	  * @param username  FTP登录账号
	  * @param password   FTP登录密码
	  * @param remotePath   FTP服务器上的相对路径
	  * @param fileName  要下载的文件名
	  * @param localPath  下载后保存到本地的路径
	  * @return
	  */
	 public boolean downFile(String url, int port, String username,
	   String password, String remotePath, String fileName,
	   String localPath) {
	  // 初始表示下载失败
	  boolean success = false;
	  // 创建FTPClient对象
	  FTPClient ftp = new FTPClient();
	  try {
	   int reply;
	   // 连接FTP服务器
	   // 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
	   ftp.connect(url, port);
	   // 登录ftp
	   ftp.login(username, password);
	   reply = ftp.getReplyCode();
	   if (!FTPReply.isPositiveCompletion(reply)) {
	    ftp.disconnect();
	    return success;
	   }      // 转到指定下载目录
	   ftp.changeWorkingDirectory(remotePath);
	   // 列出该目录下所有文件
	   FTPFile[] fs = ftp.listFiles();
	   // 遍历所有文件,找到指定的文件
	   for (FTPFile ff : fs) {
	    if (ff.getName().equals(fileName)) {
	     // 根据绝对路径初始化文件
	     File localFile = new File(localPath + "/" + ff.getName());
	     // 输出流
	     OutputStream is = new FileOutputStream(localFile);
	     // 下载文件
	     ftp.retrieveFile(ff.getName(), is);
	     is.close();
	    }
	   }
	   // 退出ftp
	   ftp.logout();
	   // 下载成功
	   success = true;
	  } catch (IOException e) {
	   e.printStackTrace();
	  } finally {
	   if (ftp.isConnected()) {
	    try {
	     ftp.disconnect();
	    } catch (IOException ioe) {
	    }
	   }
	  }
	  return success;
	 }

	/**
	 * 将本地文件上传到FTP服务器上
	 */
	@Test
	public void testUpLoadFromDisk() {
		try {
			FileInputStream in = new FileInputStream(new File("D:/test.txt"));
			boolean flag = uploadFile("10.28.21.114", 21, "voole", "huilan",
					"C:/inetpub/ftproot", "a.txt", in);
			System.out.println(flag);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 在FTP服务器上生成一个文件,并将一个字符串写入到该文件中
	 */
	@Test
	public void testUpLoadFromString() {
		try {
			InputStream input = new ByteArrayInputStream("test ftp"
					.getBytes("utf-8"));
			boolean flag = uploadFile("127.0.0.1", 21, "test", "test",
					"D:/ftp", "test.txt", input);
			System.out.println(flag);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

}

 

 

二、利用org.apache.commons.net.ftp包实现一个简单的ftp客户端实用类。主要实现一下功能

      1.支持上传下载。支持断点续传

      2.支持进度汇报

      3.支持对于中文目录及中文文件创建的支持。

 

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 open.mis.data.DownloadStatus;   
import open.mis.data.UploadStatus;   
  
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;   
  
/** *//**  
 * 支持断点续传的FTP实用类  
 * @author BenZhou  http://www.bt285.cn
 * @version 0.1 实现基本断点上传下载  
 * @version 0.2 实现上传下载进度汇报  
 * @version 0.3 实现中文目录创建及中文文件创建,添加对于中文的支持  
 */  
public class ContinueFTP {   
    public 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);   
        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;   
    }   
       
    public static void main(String[] args) {   
        ContinueFTP myFtp = new ContinueFTP();   
        try {   
            myFtp.connect("192.168.21.181", 21, "nid", "123");   
//          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"));   
            myFtp.disconnect();   
        } catch (IOException e) {   
            System.out.println("连接FTP出错:"+e.getMessage());   
        }   
    }   
}  
分享到:
评论
6 楼 ncx1259988 2011-08-17  
请问支持客户端下载吗,比如A电脑部署了项目和FTP服务器,我到B电脑去访问项目下载文件,可以下载到B电脑里面去吗,我遇到一个问题就是在A电脑下载可以下载到C盘,可以我到B电脑上面去也是下载到A电脑的C盘,而我想要的结果是下载到B电脑的C盘,请问兄弟你有什么好的解决方法没,感激不尽!
5 楼 huwenbiao2010 2011-03-05  
DownloadStatus这个类可以贴出来吗?
4 楼 hua839 2011-01-25  
谢谢!谢谢!谢谢!
3 楼 追求幸福 2010-12-09  
请问如何导入apache的commons net包呀??
2 楼 jeye_ID 2010-05-28  

请问这个import open.mis.data.DownloadStatus;
DownloadStatus这个类可以贴出来吗?
1 楼 xiaobojava 2010-05-19  
如果有很多的文件比如200个文件,你这样连续下有出现假死。不知道有没有遇到?

相关推荐

    FTPClient上传下载(支持断点续传)

    该资源源于网络,支持断点续传,资源不错,与大家分享

    java common FTPClient ftp sftp

    阅读建议:此资源以让工作中的同学快速学习使用,直接复制代码即可直接使用,不需要太多改造,当然也有更好的方法,很多需要完善的地方都可以自己随意改动。本来想直接boke形式直接贴出来的,但是代码太多了。收5...

    java源码包---java 源码 大量 实例

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java源码包4

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    JAVA上百实例源码以及开源项目

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java源码包2

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    JAVA上百实例源码以及开源项目源代码

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    java源码包3

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密 Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。 设定字符串为“张三,你好,我是李四”...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密 Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。 设定字符串为“张三,你好,我是李四”...

Global site tag (gtag.js) - Google Analytics