我最近由于在做一个关于FTP文件上传和下载的功能时候,发现Apache FTP jar包没有提供对整个目录结构的上传和下载功能,只能非目录类型的文件进行上传和下载操作,后来我查阅很多网上的实现方法,再结合自己的理解、以及符合自己的需求,完成了我自己的apache FTP jar包补充类。
上面是背景,基本叙述完毕,下面开始介绍实现方法和代码。
一。环境搭建:
1.使用的FileZilla Server开源免费软件,安装过后建立的本地FTP服务器。
2.使用的apache上下载FTP工具包,引用到工程目录中。
3.IDE,Eclipse,JDK6
二。介绍代码。
上传和下载目录的实现原理:对每一个层级的目录进行判断,是为目录类型、还是文件类型。
如果为目录类型,采用递归调用方法,检查到最底层的目录为止结束。
如果为文件类型,则调用上传或者下载方法对文件进行上传或者下载操作。
贴出代码:(其中有些没有代码,可以看看,还是很有用处的)
package com.ftp; 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.net.SocketException; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPClientConfig; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; public class RemoteFtpProcess extends FTPClient { private static FTPClient ftpClient = new FTPClient(); /** * 本方法用户登录远程的FTP服务器 * * @param url :表示FTP的IP地址 * @param port :FTP服务器端口,默认端口为21 * @param userName :登录FTP的用户名 * @param password :登录FTP的密码 * * @return FTPClient:返回为FTPClient对象 */ public FTPClient loginFtp(String url, int port, String userName, String password) { try { ftpClient.connect(url, port); ftpClient.setControlEncoding("UTF-8"); FTPClientConfig ftpConfig = new FTPClientConfig(FTPClientConfig.SYST_NT); ftpConfig.setServerLanguageCode("zh"); ftpClient.login(userName, password); int reply = 0; reply = ftpClient.getReplyCode(); System.out.println(reply); if (FTPReply.isPositiveCompletion(reply)) { System.out.println("登录成功!"); } else { System.out.println("登录失败!"); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return ftpClient; } /** * @param ftpc :退出FTP登录 * @return boolean :是否已经关闭连接 * * @throws IOException */ public static boolean closeConnections(FTPClient ftpc) throws IOException { boolean bool = false; ftpc.logout(); return bool; } /** * 方法用于上传文件到FTP服务器的指定文件夹中 * * @param fileName :上传文件的名称 * @param input :上传文件的输入流对象 * @param toFtpPath :上传到FTP的目的路径 * * @return boolean:表示上传是否成功 * */ public boolean uploadFileToFtp(String fileName, InputStream input, String toFtpPath) { boolean bool = false; try { // 使得能够处理中文编码 fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1"); toFtpPath = new String(toFtpPath.getBytes("GBK"), "ISO-8859-1"); // 转到上传文件的FTP目录中 ftpClient.changeWorkingDirectory(toFtpPath); // 设置处理文件的类型为字节流的形式 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // 如果缺省该句 传输txt正常 但图片和其他格式的文件传输出现乱码 ftpClient.storeFile(fileName, input); input.close(); bool = true; } catch (IOException e) { bool = false; e.printStackTrace(); } return bool; } /** * 方法用于从FTP服务器中下载文件 * * @param ftpUrl :下载文件所处FTP中路径 * @param fileName :下载的文件名称 * @param outputSream :下载文件的输出流对象 * * @return boolean :表示是否上传成功 * */ public boolean downloadFileFromFtp(String ftpUrl, String fileName, OutputStream outputStream) { boolean bool = false; try { ftpClient.changeWorkingDirectory(ftpUrl); FTPFile[] ftpFile = ftpClient.listFiles(); for (int i = 0; i < ftpFile.length; i++) { if (fileName.equals(ftpFile[i].getName())) { ftpClient.retrieveFile(new String(ftpFile[i].getName() .getBytes("GBK"), "ISO-8859-1"), outputStream); outputStream.flush(); outputStream.close(); } } bool = true; } catch (IOException e) { e.printStackTrace(); bool = false; } return bool; } /** * 方法用户删除FTP上的指定的文件 * * @param fileUrl :文件在FTP中的路径 * @param fileName :文件的名称 * * @return boolean:删除是否成功 */ public boolean deleteFileOnFtp(String fileUrl, String fileName) { boolean bool = false; try { ftpClient.changeWorkingDirectory(fileUrl); FTPFile[] ftpFiles = ftpClient.listFiles(); System.out.println(ftpFiles.length); for (int i = 0; i < ftpFiles.length; i++) { if (fileName.equals(ftpFiles[i].getName())) { ftpClient.deleteFile(fileName); } } } catch (IOException e) { e.printStackTrace(); } return bool; } /** * 判断指定文件中是否存在相同名称的文件 * * @param remotePath :FTP上的远程目录 * @param fileName:文件名称 * @return boolean :判断是否存在相同名称 * */ public boolean isSameName(String remotePath, String fileName) { boolean bool = false; try { FTPFile[] ftpFiles = ftpClient.listFiles(); System.out.println(ftpFiles.length); ftpClient.changeWorkingDirectory(remotePath); for (int i = 0; i < ftpFiles.length; i++) { if (fileName.equals(ftpFiles[i].getName())) { System.out.println("存在和指定文件相同名称的文件"); bool = true; } else { bool = false; } } } catch (Exception e) { bool = false; } return bool; } /** * 更改文件名称 * */ public String changeName(String remotePath, String fileName, String newName) { if (isSameName(remotePath, fileName)) { fileName = fileName + "." + newName; } return fileName; } public static void newFileOnFTP(String pathName){ try { ftpClient.mkd(pathName); } catch (IOException e) { e.printStackTrace(); } } //上传整个目录到FTP的指定目录中 public void uploadDirFiles(String dirPath,String toRemotePath) throws IOException{ if (dirPath!=null && !dirPath.equals("")) { //建立上传目录的File对象 File dirFile = new File(dirPath); //判断File对象是否为目录类型 if (dirFile.isDirectory()) { //如果是目录类型。 //在FTP上创建一个和File对象文件相同名称的文件夹 ftpClient.makeDirectory(toRemotePath+"//"+dirFile.getName()); //获得File对象中包含的子目录数组 File[] subFiles = dirFile.listFiles(); //路径 String path = toRemotePath+"//"+dirFile.getName(); System.out.println(path); //判断数组是否为空 if (subFiles!=null && subFiles.length>0) { //遍历整个File数组 for (int i = 0; i < subFiles.length; i++) { //判断是否为目录类型 if (subFiles[i].isDirectory()) { //如果为目录类型 //跳转到FTP的根目录层级 ftpClient.changeWorkingDirectory("//"); //在FTP上建立相同的目录名称 ftpClient.makeDirectory(path+"//"+subFiles[i].getName()); //递归调用自身方法,进行到下一层级的目录循环 uploadDirFiles(subFiles[i].getAbsolutePath(), path); } else { //如果为文件类型 //建立一个文件输出流对象 FileInputStream input = new FileInputStream(subFiles[i]); //调用文件上传方法,将文件上传到FTP上 uploadFileToFtp(subFiles[i].getName(), input, path+"//"); //关闭文件输入流 input.close(); } } } } else { //如果为文件类型 //建立一个文件输出流对象 FileInputStream input = new FileInputStream(dirFile); //调用文件上传方法,将文件上传到FTP上 uploadFileToFtp(dirFile.getName(), input, toRemotePath); //关闭文件输入流 input.close(); } } } //本方法用于下载FTP上的目录结构到本地中 public void downloadDirFiles(String remotePath,String localPath,String fileName) throws IOException{ if (remotePath!=null && !remotePath.equals("")) { //在本地建立一个相同的文件目录 File localFile = new File(localPath+"\\"+fileName); localFile.mkdirs(); //获得目录在本地的绝对路径 localPath = localFile.getAbsolutePath(); System.out.println(localPath); //获得FTPFile对象数组 FTPFile[] ftpFiles = ftpClient.listFiles(new String(remotePath.getBytes("GBK"),"ISO-8859-1")); if (ftpFiles!=null && ftpFiles.length>0) { for (int i = 0; i < ftpFiles.length; i++) { FTPFile subFile = ftpFiles[i]; //判断是否为目录结构 if (subFile.isDirectory()) { //如果为目录结构 //调用自身方法,进行下一层级目录循环 downloadDirFiles(remotePath+"//"+subFile.getName(), localPath, subFile.getName()); } else { //如果不为目录结构,为文件类型 FileOutputStream outputStream = new FileOutputStream(new File(localPath+"\\"+subFile.getName())); //调用下载方法对文件进行下载 downloadFileFromFtp(remotePath, subFile.getName(), outputStream); //关闭文件输出流 outputStream.close(); } } } } } }
package com.ftp; import java.io.IOException; import org.apache.commons.net.ftp.FTPClient; public class TestMain { public static void upload(){ RemoteFtpProcess remote = new RemoteFtpProcess(); FTPClient ftpClient = remote.loginFtp("127.0.0.1", 21, "root", "root"); try { remote.uploadDirFiles("D:\\FTPTestA", "//"); } catch (IOException e) { e.printStackTrace(); } } public static void download(){ RemoteFtpProcess remote = new RemoteFtpProcess(); FTPClient ftpClient = remote.loginFtp("127.0.0.1", 21, "root", "root"); try { remote.downloadDirFiles("\\FTPTest", "E://", "FTPTestB "); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { download(); } }
有什么更好地建议或者方法,请直接评论回答。
===============Over========================