apache fip 工具类

方德宇
2023-12-01

package com.isoftstone.common.utils.ftp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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 java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ProtocolCommandListener;
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 com.isoftstone.common.utils.Configuration;

/**
 * 支持断点续传的FTP实用类
 *
 * @version 0.1 实现基本断点上传下载
 * @version 0.2 实现上传下载进度汇报
 * @version 0.3 实现中文目录创建及中文文件创建,添加对于中文的支持
 */
public class FTPTools {

 // 获取配置文件连接信息
 static FTPClient ftpClient = null;
 static String strServerip = ""; // FTP服务器IP
 static String strServeruser = ""; // FTP服务器帐号
 static String strServerpassword = ""; // FTP服务器密码
 static String strServerurl = ""; // FTP服务器根路径
 static int iServerport = 0; // FTP服务器端口

 static {
  /*-------------获取配置文件常量 start------------*/
  Configuration rc = new Configuration("config.properties");// 相对路径
  if (rc.getValue("serverip") != null
    && !"".equals(rc.getValue("serverip"))) {
   strServerip = rc.getValue("serverip");
  }
  if (rc.getValue("serveruser") != null
    && !"".equals(rc.getValue("serveruser"))) {
   strServeruser = rc.getValue("serveruser");
  }
  if (rc.getValue("serverpassword") != null
    && !"".equals(rc.getValue("serverpassword"))) {
   strServerpassword = rc.getValue("serverpassword");
  }
  if (rc.getValue("serverurl") != null
    && !"".equals(rc.getValue("serverurl"))) {
   strServerurl = rc.getValue("serverurl");
  }
  if (rc.getValue("serverport") != null
    && !"".equals(rc.getValue("serverport"))) {
   iServerport = Integer.parseInt(rc.getValue("serverport"));
  }
  /*-------------获取FTP连接   start------------*/

 }

 // 枚举类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; // 全新下载文件失败
 }
 /**
  *
  *
  * @Description: 设置编码
  *
  * @param code   
  * @return void    
  * @throws
  */
 public void setEncoding(String code) {
  ftpClient.setControlEncoding(code);
 }

 /**
  * 连接到FTP服务器
  *
  * @param hostname
  *            主机名
  * @param port
  *            端口
  * @param username
  *            用户名
  * @param password
  *            密码
  * @return 是否连接成功
  * @throws IOException
  */
 public static boolean connect(String encoding) throws IOException {
  if (ftpClient != null && ftpClient.isConnected())
   return false;
  ftpClient = new FTPClient();
  ftpClient.setControlEncoding(encoding);
  ftpClient.addProtocolCommandListener(new PrintCommandListener(
    new PrintWriter(System.out)));
  ftpClient.connect(strServerip, iServerport);
  if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
   if (ftpClient.login(strServeruser, strServerpassword)) {
    return true;
   }
  }
  disconnect();
  return false;
 }

  /**
   * 返回FTP目录下的文件列表
   * @param ftpDirectory
   * @return
   */
   public static List<String> getFileNameList(String ftpDirectory)
   {
      List<String> list = new ArrayList<String>();
      try 
      {
         FTPFile[] filenames =  ftpClient.listFiles(ftpDirectory);
         for(FTPFile fn : filenames){
          if (fn.isFile()) {
           list.add(fn.getName());
          }
         }
      }catch(Exception e){
         e.printStackTrace();
      }
      return list;
   } 
   /**
    *
    *
    * @Description: 删除文件夹
    *
    * @param path
    * @param isAll
    * @return
    * @throws IOException   
    * @return boolean    
    * @throws
    */
   public boolean removeDirectory(String path, boolean isAll)
   throws IOException {

    if (!isAll) {
    return removeDirectory(path);
    }
 
    FTPFile[] ftpFileArr = ftpClient.listFiles(path);
    if (ftpFileArr == null || ftpFileArr.length == 0) {
    return removeDirectory(path);
    }
    //
    for (FTPFile ftpFile : ftpFileArr) {
    String name = ftpFile.getName();
    if (ftpFile.isDirectory()) {
     System.out.println("* [sD]Delete subPath ["+path + "/" + name+"]");
     removeDirectory(path + "/" + name, true);
    } else if (ftpFile.isFile()) {
     System.out.println("* [sF]Delete file ["+path + "/" + name+"]");
     deleteFile(path + "/" + name);
    }
   }
   return ftpClient.removeDirectory(path);
   }

  
   /**
    *
    *
    * @Description: 删除FTP文件
    *
    * @param pathName
    * @return
    * @throws IOException   
    * @return boolean    
    * @throws
    */
   public static boolean deleteFile(String pathName) throws IOException {
    return ftpClient.deleteFile(pathName);
      }
  
 /**
  * 从FTP服务器上下载文件,支持断点续传,上传百分比汇报
  *
  * @param remote
  *            远程文件路径
  * @param local
  *            本地文件路径
  * @return 上传的状态
  * @throws IOException
  */
  public static DownloadStatus download(String remote, String local)
   throws IOException {
  // 设置被动模式
  ftpClient.enterLocalPassiveMode();
  // 设置以二进制方式传输
  ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
  DownloadStatus result;
  
  // 检查远程文件是否存在
  FTPFile[] files = ftpClient.listFiles(remote);
  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(remote);
   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);
     // 更新文件下载进度,值存放在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(remote);
   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);
     // 更新文件下载进度,值存放在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 static 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(File.separator)) {
   //remoteFileName = remote.substring(remote.lastIndexOf(File.separator) + 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"));
  FTPFile[] files = ftpClient.listFiles(remote);
  File f =  new File(local);
  if (files.length == 1) {
   long remoteSize = files[0].getSize();
   
   long localSize = f.length();
   if (remoteSize == localSize) {
    return UploadStatus.File_Exits;
   } else if (remoteSize > localSize) {
    return UploadStatus.Remote_Bigger_Local;
   }

   // 尝试移动文件内读取指针,实现断点续传
   result = uploadFile(remote, f, ftpClient, remoteSize);

   // 如果断点续传没有成功,则删除服务器上文件,重新上传
   if (result == UploadStatus.Upload_From_Break_Failed) {
    if (!ftpClient.deleteFile(remote)) {
     return UploadStatus.Delete_Remote_Faild;
    }
    result = uploadFile(remote, f, ftpClient, 0);
   }
  } else {
   result = uploadFile(remote, f, ftpClient, 0);
  }
  return result;
 }

 /**
  * 断开与远程服务器的连接
  *
  * @throws IOException
  */
 public static void disconnect() {
  try {
   if (ftpClient.isConnected()) {
    ftpClient.disconnect();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 /**
  * 递归创建远程服务器目录
  *
  * @param remote
  *            远程服务器文件绝对路径
  * @param ftpClient
  *            FTPClient 对象
  * @return 目录创建是否成功
  * @throws IOException
  */
 private static UploadStatus CreateDirecroty(String remote,
   FTPClient ftpClient) throws IOException {
  UploadStatus status = UploadStatus.Create_Directory_Success;
  String directory = remote.substring(0, remote.lastIndexOf(File.separator) + 1);
  if (!directory.equalsIgnoreCase(File.separator)
    && !ftpClient.changeWorkingDirectory(directory)) {
   // 如果远程目录不存在,则递归创建远程服务器目录
   int start = 0;
   int end = 0;
   if (directory.startsWith(File.separator)) {
    start = 1;
   } else {
    start = 0;
   }
   end = directory.indexOf(File.separator, start);
   while (true) {
    String subDirectory = remote.substring(start, end);
    if (!ftpClient.changeWorkingDirectory(File.separator+subDirectory)) {
     if (ftpClient.makeDirectory(subDirectory)) {
      ftpClient.changeWorkingDirectory(subDirectory);
     } else {
      System.out.println("创建目录失败");
      return UploadStatus.Create_Directory_Fail;
     }
    }

    start = end + 1;
    end = directory.indexOf(File.separator, start);

    // 检查所有目录是否创建完毕
    if (end <= start) {
     break;
    }
   }
  }
  return status;
 }

 /**
  * 上传文件到服务器,新上传和断点续传
  *
  * @param remoteFile
  *            远程文件名,在上传之前已经将服务器工作目录做了改变
  * @param localFile
  *            本地文件 File句柄,绝对路径
  * @param processStep
  *            需要显示的处理进度步进值
  * @param ftpClient
  *            FTPClient 引用
  * @return
  * @throws IOException
  */
 private static 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;
  long localcount = 0L;
  RandomAccessFile raf = new RandomAccessFile(localFile, "r");
  OutputStream out = ftpClient.appendFileStream(remoteFile);
  // 断点续传
  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;
   localcount = (localreadbytes/100)*100;
   if (localcount / step != process) {
    process = localcount / step;
    System.out.println("上传进度:" + process);
    // 汇报上传状态
   }
  }
  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;
 }
 /**
  *
  *
  * @Description: 文件是否存着
  *
  * @param path
  * @return
  * @throws IOException   
  * @return boolean    
  * @throws
  */
 public static boolean existDirectory(String path) throws IOException {
  boolean flag = false;
  FTPFile[] ftpFileArr = ftpClient.listFiles(path);
  for (FTPFile ftpFile : ftpFileArr) {
  if (ftpFile.isDirectory()
  && ftpFile.getName().equalsIgnoreCase(path)) {
  flag = true;
  break;
  }
  }
  return flag;
 }
 
 /**
  *
  *
  * @Description: 改变工作目录
  *
  * @param path
  * @return
  * @throws IOException   
  * @return boolean    
  * @throws
  */
 public static boolean changeDirectory(String path) throws IOException {
  return ftpClient.changeWorkingDirectory(path);
 }
 /**
  *
  *
  * @Description: 创建目录
  *
  * @param pathName
  * @return
  * @throws IOException   
  * @return boolean    
  * @throws
  */
 public static boolean createDirectory(String pathName) throws IOException {
  return ftpClient.makeDirectory(pathName);
 }
 /**
  *
  *
  * @Description: 删除文件
  *
  * @param path
  * @return
  * @throws IOException   
  * @return boolean    
  * @throws
  */
 public static boolean removeDirectory(String path) throws IOException {
  return ftpClient.removeDirectory(path);
 }
 /**
  *
  *
  * @Description: 重命名
  *
  * @param from
  * @param to
  * @return
  * @throws IOException   
  * @return boolean    
  * @throws
  */
 public static boolean renameDirectory(String from,String to) throws IOException {
  return ftpClient.rename(from,to);
 }
 /**
  * 将路径和文件名拼接起来
  *
  * @param folderPath
  *            某一文件夹路径字符串,e.g. "c:\cs\" 或 "c:\cs"
  * @param fileName
  *            某一文件名字符串, e.g. "cs.txt"
  * @return 文件全路径的字符串
  */
 public static String makeFilePath(String folderPath, String fileName) {
  return folderPath.endsWith("\\") || folderPath.endsWith("/") ? folderPath
    + fileName
    : folderPath + File.separatorChar + fileName;
 }
 
 /**
  *
  *
  * @Description: 复制文件夹 (未调试通过)
  *
  * @param fileNameFrom
  * @param fileNameTo
  * @return   
  * @return boolean    
  * @throws
  */
 public static boolean copyDirectoryBug(String fileNameFrom, String fileNameTo) {
 
  try {
      // 设置PassiveMode传输
   ftpClient.enterLocalPassiveMode();
   // 设置以二进制流的方式传输
   ftpClient.setFileType(FTP.BINARY_FILE_TYPE, FTP.BINARY_FILE_TYPE);
   ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);         
  //createDirectory(fileNameTo); // 如果文件夹不存在 则建立新文件夹
  FTPFile[] ftpFileArr = ftpClient.listFiles(fileNameFrom);
  for (int i = 0; i < ftpFileArr.length; i++) {
   if (ftpFileArr[i].isFile()) {
     ByteArrayOutputStream bos = new ByteArrayOutputStream();
     ByteArrayInputStream is = null;
     try {
      if (ftpClient.retrieveFile(makeFilePath(fileNameFrom, ftpFileArr[i].getName()), bos)) {
       is = new ByteArrayInputStream(bos.toByteArray());
       bos.flush();
       if (ftpClient.storeFile(makeFilePath(fileNameTo, ftpFileArr[i].getName()), is)) {
        System.err.println("File OK.");
       }
      }else{
       return false;
      }
  
     } catch (Exception e) {
     e.getStackTrace();
     } finally {
      try {
       bos.close();
       if (is!=null) {
       is.close();
      }
      } catch (Exception e) {
       e.getStackTrace();
      }
     }
   } else if (ftpFileArr[i].isDirectory()) {// 如果是子文件夹
    copyDirectoryBug(fileNameFrom + '/' + ftpFileArr[i], fileNameTo + '/'
      + ftpFileArr[i]);
   }
  }
  } catch (Exception e) {
   e.printStackTrace();
   }
  return true;
 }
 /**
  *
  *
  * @Description: 复制文件
  *
  * <listeners>
  * <nio-listener name="other" port="2121">
  *     <ssl>
     *            <keystore file="./res/ftpserver.jks" password="password" />
     *        </ssl>
  * </nio-listener>
  * </listeners>
  *    
  * @return void    
  * @throws
  */
 public static void copyDirectory(){
  //设置端口 需要设置两个 并且需要修改ftp    ftpd-typical.xml 配置文件
  int port1 = 21, port2 = 2121;
  FTPClient ftp1, ftp2;
  ProtocolCommandListener listener;

  listener = new PrintCommandListener(new PrintWriter(System.out), true);
  ftp1 = new FTPClient();
  ftp1.setControlEncoding("UTF-8");
  ftp1.addProtocolCommandListener(listener);
  ftp2 = new FTPClient();
  ftp2.setControlEncoding("UTF-8");
  ftp2.addProtocolCommandListener(listener);
  String server1 = "10.10.87.162";
  try {
   int reply;

   if (port1 > 0) {
    ftp1.connect(server1, port1);
   } else {
    ftp1.connect(server1);
   }
   System.out.println("Connected to " + server1 + ".");

   reply = ftp1.getReplyCode();

   if (!FTPReply.isPositiveCompletion(reply)) {
    ftp1.disconnect();
    System.err.println("FTP server1 refused connection.");
    System.exit(1);
   }
  } catch (IOException e) {
   if (ftp1.isConnected()) {
    try {
     ftp1.disconnect();
    } catch (IOException f) {
     // do nothing
    }
   }
   System.err.println("Could not connect to server1.");
   e.printStackTrace();
   System.exit(1);
  }

  String server2 = "10.10.87.162";
  try {
   int reply;
   if (port2 > 0) {
    ftp2.connect(server2, port2);
   } else {
    ftp2.connect(server2);
   }
   System.out.println("Connected to " + server2 + ".");

   reply = ftp2.getReplyCode();

   if (!FTPReply.isPositiveCompletion(reply)) {
    ftp2.disconnect();
    System.err.println("FTP server2 refused connection.");
    System.exit(1);
   }
  } catch (IOException e) {
   if (ftp2.isConnected()) {
    try {
     ftp2.disconnect();
    } catch (IOException f) {
     // do nothing
    }
   }
   System.err.println("Could not connect to server2.");
   e.printStackTrace();
   System.exit(1);
  }

  __main: try {
   if (!ftp1.login("admin", "123456")) {
    System.err.println("Could not login to " + server1);
    break __main;
   }

   if (!ftp2.login("admin", "123456")) {
    System.err.println("Could not login to " + server2);
    break __main;
   }
   ftp1.setFileType(FTP.BINARY_FILE_TYPE);
   ftp2.setFileType(FTP.BINARY_FILE_TYPE);
   // Let's just assume success for now.
   ftp2.enterRemotePassiveMode();

   ftp1.enterRemoteActiveMode(
     InetAddress.getByName(ftp2.getPassiveHost()),
     ftp2.getPassivePort());

   if (ftp1.remoteRetrieve("/ebookcon/123456/1242397_115221077_2.jpg")
     && ftp2.remoteStore("/ebookcon/123456/bak/1242397_115221077_2.jpg")) {

    ftp1.completePendingCommand();
    ftp2.completePendingCommand();
   } else {
    System.err
      .println("Couldn't initiate transfer.  Check that filenames are valid.");
    break __main;
   }

  } catch (IOException e) {
   e.printStackTrace();
   System.exit(1);
  } finally {
   try {
    if (ftp1.isConnected()) {
     ftp1.logout();
     ftp1.disconnect();
    }
   } catch (IOException e) {
    // do nothing
   }

   try {
    if (ftp2.isConnected()) {
     ftp2.logout();
     ftp2.disconnect();
    }
   } catch (IOException e) {
    e.getStackTrace();
   }
  }
 }
 
 
 
 /**
  *
  *
  * @Description:  复制文件
  *
  * @param sourcePath
  * @param targetPath
  * @return
  * @throws IOException   
  * @return boolean    
  * @throws
  */ 
 public static void copyFile(String sourcePath,String targetPath) {
  try {
   ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
   ftpClient.enterLocalPassiveMode();
   // ftpClient.changeWorkingDirectory("ebookcon/123456");
   FTPFile[] ftpFiles = ftpClient.listFiles(sourcePath);

   for (FTPFile file : ftpFiles) {

    System.err.println(file.getType());
    InputStream inputStream = ftpClient.retrieveFileStream(sourcePath
      + file.getName());

    FileOutputStream ops = new FileOutputStream(new File("C:/"
      + file.getName()));
    ReadableByteChannel byteChannel = Channels
      .newChannel(inputStream);
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 10);

    FileChannel outChannel = ops.getChannel();
    int readSize = 0;
    int curSize = 0;
    while ((readSize = byteChannel.read(byteBuffer)) != -1) {
     curSize += readSize;
     byteBuffer.flip();
     outChannel.write(byteBuffer);
     byteBuffer.clear();
     System.err.println(curSize + "  :  " + readSize);
    }
    byteBuffer = null;
    ops.close();
    inputStream.close();
    if (!ftpClient.completePendingCommand()) {
     ftpClient.logout();
     ftpClient.disconnect();
     System.err.println("File transfer failed.");
     System.exit(1);
    }

   }

  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 
 
 
 /**
  * 关闭输入流。
  *
  * @param is
  *            输入流,可以是null。
  */
 public static void closeInputStream(InputStream is) {
  if (is != null) {
   try {
    is.close();
   } catch (IOException e) {
   }
  }
 }

 public static void closeOutputStream(OutputStream fos) {
  if (fos != null) {
   try {
    fos.close();
   } catch (IOException e) {
   }
  }
 }
 
 public static void main(String[] args) {
  try {
   
   FTPTools.connect("UTF-8");
   FTPTools.copyDirectoryBug("\\ebookcon\\123456", "\\ebookcon\\bbbb");
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   FTPTools.disconnect();
  }
 }
 

}

 类似资料: