我最近由于在做一个关于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();
}
}
}
}
}
}

编写一个测试main类,进行测试。

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();
}
}

本文转自:http://blog.csdn.net/CaptainGan/article/details/6970332

使用递归方法实现,向FTP服务器上传整个目录结构、从FTP服务器下载整个目录到本地的功能的更多相关文章

  1. ftp服务器搭建(windows)+实现ftp图片上传对接

    ftp服务器搭建(windows): vsftpd简介: vsftpd是“very secure FTP daemon”的缩写,是一个完全免费的.开放源代码的ftp服务器软件. 下载地址: http: ...

  2. 【FTP】C# System.Net.FtpClient库连接ftp服务器(上传文件)

    如果自己单枪匹马写一个连接ftp服务器代码那是相当恐怖的(socket通信),有一个评价较高的dll库可以供我们使用. 那就是System.Net.FtpClient,链接地址:https://net ...

  3. Spring学习---Spring中利用组件实现从FTP服务器上传/下载文件

    FtpUtil.java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExcepti ...

  4. Python向FTP服务器上传文件

    上传 代码示例: #!/usr/bin/python # -*- coding:utf-8 -*- from ftplib import FTP ftp = FTP() # 打开调试级别2, 显示详细 ...

  5. ftp服务器上传下载共享文件

    1 windows下搭建ftp服务器 https://blog.csdn.net/qq_34610293/article/details/79210539 搭建好之后浏览器输入 ftp://ip就可以 ...

  6. FTP服务器上传,下载文件

    public class FtpUtil { /** * * @param host FTP服务器地址 * @param port FTP服务器端口 * @param username FTP登录账号 ...

  7. Java语言实现简单FTP软件------>上传下载管理模块的实现(十一)

    1.上传本地文件或文件夹到远程FTP服务器端的功能. 当用户在本地文件列表中选择想要上传的文件后,点击上传按钮,将本机上指定的文件上传到FTP服务器当前展现的目录,下图为上传子模块流程图 选择好要上传 ...

  8. 使用ftp软件上传下载php文件时换行丢失bug

    正 文:   在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下notepad++编辑器写好的php文件,在使用ftp上传到linux服务器后,php文件的换行符全部丢失了, ...

  9. FTP客户端上传下载Demo实现

    1.第一次感觉MS也有这么难用的MFC类: 2.CFtpFileFind类只能实例化一个,多个实例同时查找会出错(因此下载时不能递归),采用队列存储目录再依次下载: 3.本程序支持文件夹嵌套上传下载: ...

随机推荐

  1. 【Python】Django 如何直接返回404 被 curl,wget 捕获到

    代码示例: from django.http import Http404, HttpResponseNotFound #raise Http404(filename) return HttpResp ...

  2. Longest Common Subsequence & Substring & prefix

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  3. 菜单栏展开和收起效果(纯js)

    2014年6月25日 15:36:29 需要关注的是: 1.用cookie保存用户当前点击的菜单项,不打扰后端代码 2.通过数学计算得到要显示和隐藏的div 3.点击事件是动态绑定到a标签上的,因此当 ...

  4. Maven无法引入自定义构件依赖的解决方案

    一般情况下,使用如下命令即可将自定义构件安装到本地仓库,供其他项目使用. mvn clean install 但是也有例外,今天我就分享一下我遇到问题,供相同遭遇的同学参考下. 我使用了父POM统一管 ...

  5. 【图文详解】scrapy安装与真的快速上手——爬取豆瓣9分榜单

    写在开头 现在scrapy的安装教程都明显过时了,随便一搜都是要你安装一大堆的依赖,什么装python(如果别人连python都没装,为什么要学scrapy….)wisted, zope interf ...

  6. sqlserver临时启用和关闭约束

    select  'ALTER TABLE ['  + b.name +  '] NOCHECK CONSTRAINT ' +  a.name +';' as  禁用约束   from  sysobje ...

  7. rds材资收集

    rds:简称云数据库(Relational Database Service) RDS目前支持的数据库类型有两种:mysql,sqlserver. 阿里云RDS数据库教程菜鸟如何玩转阿里云RDS?:h ...

  8. iOS开发网络篇—网络请求(HTTP协议)小结(转)

    1. 聊一下HTTP协议(协议的完整的通信过程) 2.通信过程 1> 请求 * 客户端 --> 服务器 * 请求的内容 a. 请求行(请求方法\HTTP协议\请求资源路径) b. 请求头( ...

  9. .net学习之.net和C#关系、运行过程、数据类型、类型转换、值类型和引用类型、数组以及方法参数等

    1..net 和 C# 的关系.net 是一个平台,C#是种语言,C#语言可以通过.net平台来编写.部署.运行.net应用程序,C#通过.net平台开发.net应用程序2..net平台的重要组成FC ...

  10. Java Hour 41 Maven ( 3 )

    有句名言,叫做10000小时成为某一个领域的专家.姑且不辩论这句话是否正确,让我们到达10000小时的时候再回头来看吧. 41.1 m2eclipse 简介 m2eclipse 是一款开源工具,为ec ...