开发环境:Jdk 1.8

引入第三方库:commons-net-2.2.jar(针对第一种方法)

一、基于第三方库FtpClient的FTP服务器数据传输

由于是基于第三方库,所以这里基本上没有太多要说明的东西。就是导入第三方库再调用即可,调用过程从下面的代码可以参见。为了便于文章的完整性,这也是给出其程序结构图吧。

图-1 基于FtpClient的FTP网络文件传输图

所需要

commons.net-1.4.1.jar

jar包已保存到百度网盘ftptest中。或者http://pan.baidu.com/s/1hq5p7NI


/**
* ftp链接常量
*
*/
public class Ftp {


private String ipAddr;//ip地址

private Integer port;//端口号

private String userName;//用户名

private String pwd;//密码

private String path;//aaa路径


public String getIpAddr() {
return ipAddr;
}


public void setIpAddr(String ipAddr) {
this.ipAddr = ipAddr;
}


public Integer getPort() {
return port;
}


public void setPort(Integer port) {
this.port = port;
}


public String getUserName() {
return userName;
}


public void setUserName(String userName) {
this.userName = userName;
}


public String getPwd() {
return pwd;
}


public void setPwd(String pwd) {
this.pwd = pwd;
}


public String getPath() {
return path;
}


public void setPath(String path) {
this.path = path;
}

}

 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream; import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger; public class FtpUtil { private static Logger logger=Logger.getLogger(FtpUtil.class); private static FTPClient ftp; /**
* 获取ftp连接
* @param f
* @return
* @throws Exception
*/
public static boolean connectFtp(Ftp f) throws Exception{
ftp=new FTPClient();
boolean flag=false;
int reply;
if (f.getPort()==null) {
ftp.connect(f.getIpAddr(),21);
}else{
ftp.connect(f.getIpAddr(),f.getPort());
}
ftp.login(f.getUserName(), f.getPwd());
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return flag;
}
ftp.changeWorkingDirectory(f.getPath());
flag = true;
return flag;
} /**
* 关闭ftp连接
*/
public static void closeFtp(){
if (ftp!=null && ftp.isConnected()) {
try {
ftp.logout();
ftp.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* ftp上传文件
* @param f
* @throws Exception
*/
public static void upload(File f) throws Exception{
if (f.isDirectory()) {
ftp.makeDirectory(f.getName());
ftp.changeWorkingDirectory(f.getName());
String[] files=f.list();
for(String fstr : files){
File file1=new File(f.getPath()+"/"+fstr);
if (file1.isDirectory()) {
upload(file1);
ftp.changeToParentDirectory();
}else{
File file2=new File(f.getPath()+"/"+fstr);
FileInputStream input=new FileInputStream(file2);
ftp.storeFile(file2.getName(),input);
input.close();
}
}
}else{
File file2=new File(f.getPath());
FileInputStream input=new FileInputStream(file2);
ftp.storeFile(file2.getName(),input);
input.close();
}
} /**
* 下载链接配置
* @param f
* @param localBaseDir 本地目录
* @param remoteBaseDir 远程目录
* @throws Exception
*/
public static void startDown(Ftp f,String localBaseDir,String remoteBaseDir ) throws Exception{
if (FtpUtil.connectFtp(f)) { try {
FTPFile[] files = null;
boolean changedir = ftp.changeWorkingDirectory(remoteBaseDir);
if (changedir) {
ftp.setControlEncoding("GBK");
files = ftp.listFiles();
for (int i = 0; i < files.length; i++) {
try{
downloadFile(files[i], localBaseDir, remoteBaseDir);
}catch(Exception e){
logger.error(e);
logger.error("<"+files[i].getName()+">下载失败");
}
}
}
} catch (Exception e) {
logger.error(e);
logger.error("下载过程中出现异常");
}
}else{
logger.error("链接失败!");
} } /**
*
* 下载FTP文件
* 当你需要下载FTP文件的时候,调用此方法
* 根据<b>获取的文件名,本地地址,远程地址</b>进行下载
*
* @param ftpFile
* @param relativeLocalPath
* @param relativeRemotePath
*/
private static void downloadFile(FTPFile ftpFile, String relativeLocalPath,String relativeRemotePath) {
if (ftpFile.isFile()) {
if (ftpFile.getName().indexOf("?") == -1) {
OutputStream outputStream = null;
try {
File locaFile= new File(relativeLocalPath+ ftpFile.getName());
//判断文件是否存在,存在则返回
if(locaFile.exists()){
return;
}else{
outputStream = new FileOutputStream(relativeLocalPath+ ftpFile.getName());
ftp.retrieveFile(ftpFile.getName(), outputStream);
outputStream.flush();
outputStream.close();
}
} catch (Exception e) {
logger.error(e);
} finally {
try {
if (outputStream != null){
outputStream.close();
}
} catch (IOException e) {
logger.error("输出文件流异常");
}
}
}
} else {
String newlocalRelatePath = relativeLocalPath + ftpFile.getName();
String newRemote = new String(relativeRemotePath+ ftpFile.getName().toString());
File fl = new File(newlocalRelatePath);
if (!fl.exists()) {
fl.mkdirs();
}
try {
newlocalRelatePath = newlocalRelatePath + '/';
newRemote = newRemote + "/";
String currentWorkDir = ftpFile.getName().toString();
boolean changedir = ftp.changeWorkingDirectory(currentWorkDir);
if (changedir) {
FTPFile[] files = null;
files = ftp.listFiles();
for (int i = 0; i < files.length; i++) {
downloadFile(files[i], newlocalRelatePath, newRemote);
}
}
if (changedir){
ftp.changeToParentDirectory();
}
} catch (Exception e) {
logger.error(e);
}
}
} public static void main(String[] args) throws Exception{
Ftp f=new Ftp();
f.setIpAddr("1111");
f.setUserName("root");
f.setPwd("111111");
FtpUtil.connectFtp(f);
File file = new File("F:/test/com/test/Testng.java");
FtpUtil.upload(file);//把文件上传在ftp上
FtpUtil.startDown(f, "e:/", "/xxtest");//下载ftp文件测试
System.out.println("ok"); } }

1.FTP的连接及登录

  1. public static FtpClient connectFTP(String url, int port, String username, String password) {
  2. //创建ftp
  3. FtpClient ftp = null;
  4. try {
  5. //创建地址
  6. SocketAddress addr = new InetSocketAddress(url, port);
  7. //连接
  8. ftp = FtpClient.create();
  9. ftp.connect(addr);
  10. //登陆
  11. ftp.login(username, password.toCharArray());
  12. ftp.setBinaryType();
  13. } catch (FtpProtocolException e) {
  14. e.printStackTrace();
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. return ftp;
  19. }

2.上传文件到FTP服务器

  1. public static void upload(String localFile, String ftpFile, FtpClient ftp) {
  2. OutputStream os = null;
  3. FileInputStream fis = null;
  4. try {
  5. // 将ftp文件加入输出流中。输出到ftp上
  6. os = ftp.putFileStream(ftpFile);
  7. File file = new File(localFile);
  8. // 创建一个缓冲区
  9. fis = new FileInputStream(file);
  10. byte[] bytes = new byte[1024];
  11. int c;
  12. while((c = fis.read(bytes)) != -1){
  13. os.write(bytes, 0, c);
  14. }
  15. System.out.println("upload success!!");
  16. } catch (FtpProtocolException e) {
  17. e.printStackTrace();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. } finally {
  21. try {
  22. if(os!=null) {
  23. os.close();
  24. }
  25. if(fis!=null) {
  26. fis.close();
  27. }
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }

3.从FTP服务器下载文件

  1. public static void download(String localFile, String ftpFile, FtpClient ftp) {
  2. InputStream is = null;
  3. FileOutputStream fos = null;
  4. try {
  5. // 获取ftp上的文件
  6. is = ftp.getFileStream(ftpFile);
  7. File file = new File(localFile);
  8. byte[] bytes = new byte[1024];
  9. int i;
  10. fos = new FileOutputStream(file);
  11. while((i = is.read(bytes)) != -1){
  12. fos.write(bytes, 0, i);
  13. }
  14. System.out.println("download success!!");
  15. } catch (FtpProtocolException e) {
  16. e.printStackTrace();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. } finally {
  20. try {
  21. if(fos!=null) {
  22. fos.close();
  23. }
  24. if(is!=null){
  25. is.close();
  26. }
  27. } catch (IOException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }

二、基于Socket的FTP服务器数据传输

其实上面的基于第三方包FtpClient的方法中,原理层也是基于Socket来进行通信的。所以,我们当然也可以使用Socket直接来写这个FtpClient的代码。下面给出基于Socket通信的结构构架图。这里有一点需要大家注意一下,我们的FTP协议中有两个端口(20和21)。通常情况下,我们的21号端口就是平时大家口口相传的是FTP服务器的端口号,不过其实它只是FTP服务器中的命令端口号。它是负责传送命令给FTP,一些操作如“登录”、“改变目录”、“删除文件”,依靠这个连接发送命令就可完成。而对于20号端口号(也有可能是其它的一些端口号),对于有数据传输的操作,主要是显示目录列表,上传、下载文件,我们需要依靠另一个Socket来完成。

所以在下面的结构图中,我们可以看到我们有重新获得端口号的过程,正是这个原因。

图-2 基于Socket的FTP网络文件传输图

1.FTP连接

  1. public void connectFtp() {
  2. try {
  3. mFtpClient = new Socket(Config.FTP.HOST_IP, Config.FTP.HOST_PORT);
  4. mReader = new BufferedReader(new InputStreamReader(mFtpClient.getInputStream()));
  5. mWriter = new BufferedWriter(new OutputStreamWriter(mFtpClient.getOutputStream()));
  6. sendCommand("USER " + Config.FTP.FTP_USERNAME);
  7. sendCommand("PASS " + Config.FTP.FTP_PASSWD);
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. }
  11. }

2.向FTP服务器发送命令

  1. private void sendCommand(String command) throws IOException {
  2. if (Tools.StringTools.isEmpty(command)) {
  3. return;
  4. }
  5. if (mFtpClient == null) {
  6. return;
  7. }
  8. mWriter.write(command + "\r\n");
  9. mWriter.flush();
  10. }

3.向FTP服务器上传文件

  1. public void uploadFile(String localPath, String ftpPath) throws IOException {
  2. // 进入被动模式
  3. sendCommand("PASV");
  4. // 获得ip和端口
  5. String response = readNewMessage();
  6. String[] ipPort = getIPPort(response);
  7. String ip = ipPort[0];
  8. int port = Integer.parseInt(ipPort[1]);
  9. // 建立数据端口的连接
  10. Socket dataSocket = new Socket(ip, port);
  11. sendCommand("STOR " + ftpPath);
  12. // 上传文件前的准备
  13. File localFile = new File(localPath);
  14. OutputStream outputStream = dataSocket.getOutputStream();
  15. FileInputStream fileInputStream = new FileInputStream(localFile);
  16. // 上传文件
  17. int offset;
  18. byte[] bytes = new byte[1024];
  19. while ((offset = fileInputStream.read(bytes)) != -1) {
  20. outputStream.write(bytes, 0, offset);
  21. }
  22. System.out.println("upload success!!");
  23. // 上传文件后的善后工作
  24. outputStream.close();
  25. fileInputStream.close();
  26. dataSocket.close();
  27. }

4.从FTP服务器下载文件

  1. public void downloadFile(String localPath, String ftpPath) throws IOException {
  2. // 进入被动模式
  3. sendCommand("PASV");
  4. // 获得ip和端口
  5. String response = readNewMessage();
  6. String[] ipPort = getIPPort(response);
  7. String ip = ipPort[0];
  8. int port = Integer.parseInt(ipPort[1]);
  9. // 建立数据端口的连接
  10. Socket dataSocket = new Socket(ip, port);
  11. sendCommand("RETR " + ftpPath);
  12. // 下载文件前的准备
  13. File localFile = new File(localPath);
  14. InputStream inputStream = dataSocket.getInputStream();
  15. FileOutputStream fileOutputStream = new FileOutputStream(localFile);
  16. // 下载文件
  17. int offset;
  18. byte[] bytes = new byte[1024];
  19. while ((offset = inputStream.read(bytes)) != -1) {
  20. fileOutputStream.write(bytes, 0, offset);
  21. }
  22. System.out.println("download success!!");
  23. // 下载文件后的善后工作
  24. inputStream.close();
  25. fileOutputStream.close();
  26. dataSocket.close();
  27. }

5.断开FTP服务器连接

    1. public void disconnectFtp() {
    2. if (mFtpClient == null) {
    3. return;
    4. }
    5. if (!mFtpClient.isConnected()) {
    6. return;
    7. }
    8. try {
    9. mFtpClient.close();
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. }
    13. }

ftp链接、上传、下载、断开的更多相关文章

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

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

  2. Linux 终端访问 FTP 及 上传下载 文件

    今天同事问我一个问题,在Linux 下访问FTP,并将文件上传上去. 我之前一直是用WinSCP工具的. 先将文件从linux copy到windows下,然后在传到ftp上.google 一下. 方 ...

  3. Linux 终端訪问 FTP 及 上传下载 文件

    今天同事问我一个问题,在Linux 下訪问FTP,并将文件上传上去. 我之前一直是用WinSCP工具的. 先将文件从linux copy到windows下,然后在传到ftp上. google 一下. ...

  4. Linux 终端访问 FTP 及 上传下载 文件[转]

    1.      Linux 终端连接FTP [oracle@Dave ~]$ ftp 10.85.7.97 Connected to 10.85.7.97. 220 Serv-U FTP Server ...

  5. linux下常用FTP命令 上传下载文件【转】

    1. 连接ftp服务器 格式:ftp [hostname| ip-address]a)在linux命令行下输入: ftp 192.168.1.1 b)服务器询问你用户名和密码,分别输入用户名和相应密码 ...

  6. 使用ftp软件上传下载php文件时换行丢失bug(全部变为一行)

    文章来源:http://www.piaoyi.org/computer/ftp-php-r-n-bug.html 正 文: 在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下 ...

  7. Python 基于Python实现Ftp文件上传,下载

    基于Python实现Ftp文件上传,下载   by:授客 QQ:1033553122 测试环境: Ftp客户端:Windows平台 Ftp服务器:Linux平台 Python版本:Python 2.7 ...

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

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

  9. 【FTP】FTP文件上传下载-支持断点续传

    Jar包:apache的commons-net包: 支持断点续传 支持进度监控(有时出不来,搞不清原因) 相关知识点 编码格式: UTF-8等; 文件类型: 包括[BINARY_FILE_TYPE(常 ...

  10. ftp文件上传下载命令

    介绍:从本地以用户wasqry登录的机器1*.1**.21.67上通过ftp远程登录到ftp服务器上,登录用户名是lte****,以下为使用该连接做的实验.  查看远程ftp服务器上用户lte**** ...

随机推荐

  1. POJ 1155 TELE (树形DP,树形背包)

    题意:给定一棵树,n个节点,其中有m个叶子表示的是用户,其他点表示中转器, 每条边都有权值,每个用户i愿意给的钱w[i],问如果在不亏钱的情况下能为多少用户转播足球比赛? 思路: 其实就是要选出部分叶 ...

  2. 通过90行代码学会HTML5 WebSQL的4种基本操作

    Web SQL数据库API是一个独立的规范,在浏览器层面提供了本地对结构化数据的存储,已经被很多现代浏览器支持了. 我们通过一个简单的例子来了解下如何使用Web SQL API在浏览器端创建数据库表并 ...

  3. PAT (Basic Level) Practise (中文)-1033. 旧键盘打字(20)

    PAT (Basic Level) Practise (中文)-1033. 旧键盘打字(20)  http://www.patest.cn/contests/pat-b-practise/1033 旧 ...

  4. class extension、class category、class-continuation category

    class extension Objective-C 2.0增加了class extensions用于解决两个问题: 允许一个对象可以拥有一个私有的interface,且可由编译器验证. 支持一个公 ...

  5. 设置tableview的滚动范围--iOS开发系列---项目中成长的知识三

    设置tableview的滚动范围 有时候tableview的footerview上的内容需要向上拖动界面一定距离才能够看见, 项目中因为我需要在footerviw上添加一个按钮,而这个按钮又因为这个原 ...

  6. Python学习笔记3(字典)

    创建字典 dict函数 字典的格式化字符串 字典方法 clear copy fromkeys 序列是一个按照一定顺序将值进行组织的数据结构形式,可以通过索引对其进行征引.另外还有一种数据结构是通过名字 ...

  7. Wash!!(HDU_6000)

    传送门:Wash! 题意:有n台洗衣机,m台烘干机,给出了每台机器处理意见衣服的时间,而且没见机器同时只能处理一件衣服.问如何选择机器才能使洗完衣服的时间最短. 思路:建两个优先队列,一个表示洗衣机, ...

  8. Gitlab仓库搭建及在Linux/windows中的免密使用

    1. Gitlab简介 Gitlab:代码私有仓库,可以使用Git进行代码的管理. GitHub:公共仓库. GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭 ...

  9. The Fourth Day

    迭代器 迭代器:迭代的工具 .什么是迭代:指的是一个重复的过程,每次重复称为一次迭代,并且每次重复的结果是下一次重复的初始值 例: while True: print('====>'') l=[ ...

  10. perl学习之argument

    Arguments are the values you pass to a Perl script. Each value on the command line after the name of ...