`
jaychang
  • 浏览: 731511 次
  • 性别: Icon_minigender_1
  • 来自: 嘉兴
社区版块
存档分类
最新评论

使用commons-net包写的一个FTP上传下载类,支持断点续传,可上传整个目录

    博客分类:
  • NET
阅读更多

在http://zhouzaibao.iteye.com/blog/346000基础上进行了修改

 

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

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

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

具体请看代码,上面有详细的注释。简化版本请参见http://zhouzaibao.iteye.com/blog/342766

 

枚举类UploadStatus代码:

 

public enum DownloadStatus {
  REMOTE_FILE_NOEXIST, // 远程文件不存在
  LOCAL_BIGGER_REMOTE, // 本地文件大于远程文件
  DOWNLOAD_FROM_BREAK_SUCCESS, // 断点下载文件成功
  DOWNLOAD_FROM_BREAK_FAILED, // 断点下载文件失败
  DOWNLOAD_NEW_SUCCESS, // 全新下载文件成功
  DOWNLOAD_NEW_FAILED; // 全新下载文件失败
}

 

枚举类DownloadStatus代码:

 

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; // 删除远程文件失败
}

 

流及文件操作工具类的代码:

 

public class FileUtil {

  /**
   * 文件拷贝
   * 
   * @param insm
   * @param outsm
   * @throws IOException
   */
  public static void copyFile(File srcFile, File destFile) throws IOException {
    if (!srcFile.exists()) {
      throw new FileNotFoundException(srcFile.getName() + "不存在!");
    }
    if (!destFile.exists()) {
      destFile.createNewFile();
    }
    InputStream in = new FileInputStream(srcFile);
    OutputStream out = new FileOutputStream(destFile);
    copyStream(in, out);
  }

  /**
   * 流拷贝,通过对流的操作完成
   * 
   * @param insm
   * @param outsm
   * @throws IOException
   */
  public static void copyStream(InputStream insm, OutputStream outsm)
      throws IOException {
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    try {
      bis = new BufferedInputStream(insm);
      bos = new BufferedOutputStream(outsm);
      byte[] b = new byte[8192];
      int readBytes = -1;
      while ((readBytes = bis.read(b)) != -1) {
        bos.write(b, 0, readBytes);
      }
    } catch (IOException e) {
      e.printStackTrace();
      throw e;
    } finally {
      if (bis != null)
        bis.close();
      if (bos != null)
        bos.close();
    }
  }
}

 

 核心类FTPOperationProccessor代码:

 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import cn.com.servyou.ftpuploadtool.status.DownloadStatus;
import cn.com.servyou.ftpuploadtool.status.UploadStatus;
import cn.com.servyou.ftpuploadtool.util.FileUtil;

/**
 * <p>
 * Title: FTPOperationProcessor
 * </p>
 * 
 * <p>
 * Description: FTP操作处理类
 * </p>
 * 
 * <p>
 * Copyright: Copyright (c) 2010
 * </p>
 * 
 * @author servyou
 * 
 * @version 1.0
 */
public class FTPOperationProcessor {
  private FTPClient client = new FTPClient();
  /** 默认编码 */
  public final static String ENCODING = "GBK";

  /** FTP传输用的编码 */
  public final static String FTP_ENCODING = "ISO-8859-1";

  /** 目录前缀 */
  public final static String PREFIX = "/";

  public FTPOperationProcessor() {
    super();
  }

  /**
   * 连接FTP服务器
   * 
   * @param hostname
   *            服务器IP,或主机名
   * @param port
   *            端口号
   * @param username
   *            用户名
   * @param password
   *            密码
   * @return 连接成功返回true,失败返回false
   * @throws IOException
   */
  public boolean connect(String hostname, int port, String username,
      String password) throws IOException {
    int reply;
    client.connect(hostname);
    System.out.println("Connected to " + hostname + ".");
    System.out.println(client.getReplyString());
    reply = client.getReplyCode();
    if (!FTPReply.isPositiveCompletion(reply)) {
      client.disconnect();
      System.out.println("FTP服务器拒绝连接!");
      throw new IOException("FTP服务器拒绝连接!");
    } else {
      if (client.login(username, password)) {
        client.setListHiddenFiles(true);
        return true;
      }
    }
    return false;
  }

  /**
   * 用户登出,并关闭连接
   * 
   * @throws IOException
   */
  public void disConnect() throws IOException {
    if (client.isConnected()) {
      client.logout();
      client.disconnect();
    }
  }

  /**
   * 遍历服务器的某一目录
   * 
   * @param pathname
   *            FTP服务器的路径,如/dir1/dir2/
   * @throws IOException
   */
  public void traverseDirectory(String pathname) throws IOException {
    client.changeWorkingDirectory(pathname);
    FTPFile[] fileList = client.listFiles(pathname);
    traverse(fileList);
  }

  /**
   * 遍历FTP服务器的目录
   * 
   * @param ftpClient
   *            FTPClient
   * @param fileList
   *            文件列表
   * @throws IOException
   */
  private void traverse(FTPFile[] fileList) throws IOException {
    String tempDir = null;
    for (FTPFile file : fileList) {
      if (file.getName().equals(".") || file.getName().equals("..")) {
        continue;
      }
      if (file.isDirectory()) {
        System.out.println("***************** Directory: " + file.getName()
            + "  Start **************");
        tempDir = client.printWorkingDirectory();
        if (tempDir.matches("^((/\\w+))+$"))
          tempDir += "/" + file.getName();
        else
          tempDir += file.getName();
        client.changeWorkingDirectory(new String(tempDir.getBytes(ENCODING),
            FTP_ENCODING));
        traverse(client.listFiles(tempDir));
        // 不是目录,是文件的情况
        System.out.println("***************** Directory:" + file.getName()
            + "   End **************\n");
      } else {
        System.out.println("FileName:" + file.getName() + " FileSize:"
            + file.getSize() / (1024) + "KB" + " CreateTime:"
            + file.getTimestamp().getTime());
      }
    }
    // 遍历完当前目录,就要将工作目录改为当前目录的父目录
    client.changeToParentDirectory();
  }

  /**
   * 下载单个文件
   * 
   * @param remote
   *            远端文件
   * @param local
   *            本地文件
   * @throws IOException
   */
  public DownloadStatus download(String remote, File localFile)
      throws IOException {
    client.enterLocalPassiveMode();
    client.setFileType(FTPClient.BINARY_FILE_TYPE);
    DownloadStatus result = null;
    // 检查远程文件是否存在
    FTPFile[] files = client.listFiles(new String(remote.getBytes(ENCODING),
        FTP_ENCODING));
    if (files.length != 1) {
      System.out.println("远程文件不存在");
      return DownloadStatus.REMOTE_FILE_NOEXIST;
    }
    long lRemoteSize = files[0].getSize();
    // 本地存在文件,进行断点下载
    if (localFile.exists()) {
      long localSize = localFile.length();
      // 判断本地文件大小是否大于远程文件大小
      if (localSize >= lRemoteSize) {
        System.out.println("本地文件大于远程文件,下载中止");
        return DownloadStatus.LOCAL_BIGGER_REMOTE;
      }
      // 进行断点续传,并记录状态
      FileOutputStream out = new FileOutputStream(localFile, true);
      client.setRestartOffset(localSize);
      InputStream in = client.retrieveFileStream(new String(remote
          .getBytes(ENCODING), FTP_ENCODING));
      FileUtil.copyStream(in, out);
      boolean isDo = client.completePendingCommand();
      if (isDo) {
        result = DownloadStatus.DOWNLOAD_FROM_BREAK_SUCCESS;
      } else {
        result = DownloadStatus.DOWNLOAD_FROM_BREAK_FAILED;
      }
    } else {
      localFile.createNewFile();
      FileOutputStream out = new FileOutputStream(localFile);
      InputStream in = client.retrieveFileStream(new String(remote
          .getBytes(ENCODING), FTP_ENCODING));
      FileUtil.copyStream(in, out);
    }
    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传输
    client.enterLocalPassiveMode();
    // 设置以二进制流的方式传输
    client.setFileType(FTPClient.BINARY_FILE_TYPE);
    client.setControlEncoding(ENCODING);
    UploadStatus result;
    // 对远程目录的处理
    String remoteFileName = remote;
    if (remote.contains("/")) {
      remoteFileName = remote.substring(remote.lastIndexOf("/") + 1);
      // 创建服务器远程目录结构,创建失败直接返回
      // 以下两句存在问题??
      // if (createDirectory(remote) == UploadStatus.CREATE_DIRECTORY_FAIL) {
      // return UploadStatus.CREATE_DIRECTORY_FAIL;
      // }
    }
    // 检查远程是否存在文件
    FTPFile[] files = client.listFiles(new String(remoteFileName
        .getBytes(ENCODING), FTP_ENCODING));
    if (files != null && 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, remoteSize);
      // 如果断点续传没有成功,则删除服务器上文件,重新上传
      if (result == UploadStatus.UPLOAD_FROM_BREAK_FAILED) {
        if (!client.deleteFile(remoteFileName)) {
          return UploadStatus.DELETE_REMOTE_FAILD;
        }
        result = uploadFile(remoteFileName, f, 0);
      }
    } else {
      result = uploadFile(remoteFileName, new File(local), 0);
    }
    return result;
  }

  /**
   * 上传单个文件,断点续传功能
   * 
   * @param remote
   *            远程文件
   * @param localFile
   *            本地文件
   * @throws IOException
   */
  public UploadStatus uploadFile(String remote, File localFile, long remoteSize)
      throws IOException {
    UploadStatus status = null;
    long localreadbytes = 0l;
    RandomAccessFile raf = new RandomAccessFile(localFile, "r");
    OutputStream out = client.appendFileStream(new String(remote
        .getBytes(ENCODING), FTP_ENCODING));
    // 断点续传,根据FTP服务器上文件与本地机器上文件的大小比较来判断
    if (remoteSize > 0) {
      client.setRestartOffset(remoteSize);
      raf.seek(remoteSize);
      localreadbytes = remoteSize;
    }
    byte[] bytes = new byte[8096];
    int c;
    while ((c = raf.read(bytes)) != -1) {
      out.write(bytes, 0, c);
      localreadbytes += c;
    }
    if (out != null)
      out.flush();
    if (raf != null)
      raf.close();
    if (out != null)
      out.close();
    boolean result = client.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;
  }

  /**
   * 创建目录,(远程目录格式必须是/aaa/bbb/ccc/ddd/的形式)
   * 
   * @param remote
   *            远程目录路径
   * @throws IOException
   */
  public UploadStatus createDirectory(String remote) throws IOException {
    int start = 0, end = 0;
    start = remote.startsWith("/") ? 1 : 0;
    end = remote.indexOf("/", start);
    for (; start < end;) {
      String subDirectory = remote.substring(start, end);
      if (!client.changeWorkingDirectory(new String(subDirectory
          .getBytes(ENCODING), FTP_ENCODING))) {
        // 目录不存在则在服务器端创建目录
        if (!client.makeDirectory(new String(subDirectory.getBytes(ENCODING),
            FTP_ENCODING))) {
          return UploadStatus.CREATE_DIRECTORY_FAIL;
        } else {
          client.changeWorkingDirectory(new String(subDirectory
              .getBytes(ENCODING), FTP_ENCODING));
        }
      }
      start = end + 1;
      end = remote.indexOf("/", start);
    }
    return UploadStatus.CREATE_DIRECTORY_SUCCESS;
  }

  /**
   * 递归遍历本地机器的要上传的目录,遍历的同时,在FTP服务器上创建目录
   * (如果在FTP服务器上目录不存在的话),上传文件
   * 
   * @param directory
   *            本地目录
   * @throws IOException
   */
  private void traverseLocalDirectory(File directory) throws IOException {
    File[] files = directory.listFiles();
    if (files == null || files.length == 0) {
      client.changeToParentDirectory();
      return;
    }
    for (File file : files) {
      if (file.isDirectory()) {
        String directoryName = file.getName();
        client.makeDirectory(new String(directoryName.getBytes(ENCODING),
            FTP_ENCODING));
        client.changeWorkingDirectory(new String(directoryName
            .getBytes(ENCODING), FTP_ENCODING));
        traverseLocalDirectory(file);
      } else {
        System.out.println("FileName : " + file.getName());
        upload(file.getAbsolutePath(), client.printWorkingDirectory() + "/"
            + file.getName());
      }
    }
    client.changeToParentDirectory();
  }

  /**
   * 上传本地机器的某一目录到FTP服务器的某一路径
   * 
   * @param remoteBasePath
   *            FTP服务器的一个路径
   * @param localRootDirectoryPath
   *            本地机器需要上传的目录路径
   * @throws IOException
   */
  public UploadStatus uploadDirectory(String remoteBasePath,
      String localDirectoryPath) throws IOException {
    if (createDirectory(remoteBasePath) == UploadStatus.CREATE_DIRECTORY_FAIL) {
      return UploadStatus.CREATE_DIRECTORY_FAIL;
      // remoteBasePath FTP服务器上基目录,创建成功的话
    } else {
      if (client.changeWorkingDirectory(new String(remoteBasePath
          .getBytes(ENCODING), FTP_ENCODING))) {
        File localDirectory = new File(localDirectoryPath);
        traverseLocalDirectory(localDirectory);
        return UploadStatus.CREATE_DIRECTORY_SUCCESS;
      } else {
        return UploadStatus.CREATE_DIRECTORY_FAIL;
      }
    }
  }
}

 

 

使用方法简介:

 

1.需要创建目录:

 

FTPOperationProcessor processor = new FTPOperationProcessor();
    try {
      boolean flag = processor.connect("192.168.30.190", 21, "anonymous", "");
      if (flag == false) {
        System.out.println("连接服务器失败");
        processor.disConnect();
      } else {
         processor.createDirectory("/中1/中文的/信息/还是中文的/目录是中文的/xx林寺xxa11/");
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

 

    则可在FTP服务器的根目录生成目录

/中1/中文的/信息/还是中文的/目录是中文的/xx林寺xxa11

 

    2.上传整个目录到FTP服务器的某一目录:

 

 processor.uploadDirectory("/Jay Chang/Study/Example/", "D:\\My Documents\\Study\\Example\\");

 

    3.下载某一文件到本地:

 

 

processor.download("/backup/sys.gho", "f:\\sys.gho");

 

 

 

0
1
分享到:
评论

相关推荐

    commons-net-3.6 jar包.zip

    它提供了全面的FTP客户端实现,包括连接管理、文件上传、下载、列表操作、断点续传等功能。FTPClient类是FTP功能的主要接口,允许开发者通过简单的API调用来执行复杂的FTP任务。例如,你可以轻松地创建一个FTPClient...

    commons-net-3.3.jar

    特别是对于FTP,它不仅支持基本的文件上传和下载,还包含如文件重命名、目录管理、断点续传等功能。 二、FTPClient模块 在`commons-net-3.3.jar`中,FTPClient类是核心,它实现了完整的FTP协议。开发者可以通过创建...

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

    `FTPClient`是Apache Commons Net包中的一个类,提供了一种简单的方式来实现FTP客户端的功能,包括文件的上传、下载、目录管理等操作。通过`FTPClient`,开发者可以轻松地与FTP服务器进行交互,执行复杂的FTP命令。 ...

    commons-net-3.2

    1. **FTP(File Transfer Protocol)**:提供了全面的FTP客户端实现,支持主动和被动模式、二进制和文本传输、目录操作、断点续传等。 2. **Telnet**:实现了基本的Telnet客户端功能,允许开发者与远程系统进行交互...

    android实现ftp断点续传下载类,完成后自动通知调用程序

    在Android平台上实现FTP断点续传...综上所述,构建一个Android FTP断点续传下载类涉及多个环节,包括FTP协议的运用、断点续传的实现、进度监控以及通知机制的设计。在实际开发中,应根据具体需求进行相应的优化和调整。

    commons-net-2.2.jar_JAR包源码

    `commons-net-2.2.jar`是这个库的一个版本,其中包含了FTP文件上传功能的源代码。本文将深入探讨`commons-net`库,特别是针对FTP文件上传的实现细节。 一、Apache Commons Net库简介 Apache Commons Net是Apache...

    java ftp 多线程 断点续传等知识

    在Java中,我们可以使用`java.net`包中的`Socket`类来实现基本的FTP功能,但更常见的是使用Apache Commons Net库,它提供了更丰富的FTP功能,包括多线程和断点续传。 FTP服务器是运行FTP服务的计算机,它存储着可供...

    java ftp 上传 下载 断点续传

    Java FTP(File Transfer Protocol)是Java编程中用于与FTP服务器交互的一种技术,它允许程序员编写应用程序来上传、下载文件,并实现断点续传功能。在本文中,我们将深入探讨Java FTP上传、下载以及断点续传的核心...

    xuchuanftp_java_FTP断点续传_

    标题"XuChuanFTP_Java_FTP断点续传"可能是指一个Java实现的FTP客户端库或者一个示例项目,专注于支持FTP的断点续传功能。这个项目可能是为了帮助开发者更方便地处理大文件的上传任务,尤其是在网络不稳定的情况下。 ...

    commons-net-1.4.1.jar

    `commons-net-1.4.1.jar` 是一个Java库,属于Apache Commons项目的一部分,主要提供了对FTP(文件传输协议)的支持。这个库使得Java开发者能够方便地在他们的应用程序中执行与FTP服务器交互的各种操作,如上传、下载...

    commons-net-ftp-2.0.rar

    这个库包含了各种FTP相关的类和方法,例如FTPClient、FTPFile、FTPSSLClient等,涵盖了FTP会话的完整生命周期,包括连接、登录、文件上传、下载、目录操作、断点续传等功能。 1. **FTPClient**: 这是Apache Commons...

    commons-net-2.0源码和jar

    Apache Commons Net库是Java开发人员常用...这个库不仅提供了基本的FTP操作,还支持更高级的功能,如断点续传、文件权限管理等。对于任何需要与FTP服务器交互的Java项目,Apache Commons Net都是一个强大且可靠的工具。

    com.jcraft.jsch_0.1.31.jar和commons-net-3.2.jar

    1. **FTP客户端**:提供了全面的FTP客户端功能,包括上传、下载、目录操作、断点续传等。 2. **FTPS支持**:支持FTP over SSL/TLS,确保数据传输的安全性。 3. **TFTP支持**:简单文件传输协议(Trivial File ...

    commons-net-1.4.1.jar功能实现demo

    描述提到的是一个具体的示例程序——"FTPDemo",这是一个基于`commons-net-1.4.1.jar`的Java应用,演示了如何使用该库来与FTP服务器进行交互,实现了文件的上传和下载功能。在MyEclipse这样的集成开发环境中,这个...

    FTP断点续传

    下面是一个简单的示例代码片段,展示如何使用Java实现FTP断点续传的基本流程: ```java import org.apache.commons.net.ftp.FTPClient; public class FtpClientExample { public static void main(String[] args)...

    ftp.rar_FTP 断点续传_Java FTP上传_ftp 断点_ftp断点续传Java_java ftp

    断点续传是FTP的一个重要特性,它允许在文件传输中断后从上次停止的地方继续,而不是重新开始整个文件的传输。这对于大文件传输尤其有用,因为它可以节省时间和带宽资源。在Java中实现FTP的断点续传,主要涉及到以下...

    java写的ftp客户端,实现断点续传的上传、下载

    功能:断点续传的上传、下载。 运行:TestContinueFtp。 jar包:commons-net-1.4.0.jar 默认为主动模式,占用端口为1080。 备注:含jar包。

    java FTP多线程 批量 断点续传

    Java FTP多线程批量断点续传是一种在Java编程中实现高效、稳定文件传输的方法,尤其适用于大文件的上传和下载。在这个过程中,我们利用FTP(File Transfer Protocol)协议,结合多线程技术和断点续传功能,可以显著...

    commons-net-3.6-bin.tar

    开发者可以使用它来上传、下载、列出远程目录、重命名或删除文件,甚至进行文件的断点续传。 2. TelnetClient:提供了一个简单的telnet客户端接口,可以用来进行远程登录和交互。 3. HTTPClient:虽然Java自带了...

Global site tag (gtag.js) - Google Analytics