FTP下载时连接正常获取不到数据
今天项目中要下载快钱的对账单,快钱对账单文件的FTP服务器是Unix系统,connectServer方法中已连接成功,reply code:220。
但是问题是download方法中的ftpClient.listFiles(remote)不能找到具体某一文件,如果使用ftpClient.listFiles()而不具体指定某一远程文件时可以列举出所有的文件,包括remote这个需要下载的文件。且代码中的ftpClient.retrieveFile(remote, out);会出现长时间的等待,upNewStatus为false,最终会抛出:FTP response 421 received. Server closed connection.
public static boolean connectServer(String host, int port, String user, String password, String defaultPath)
throws SocketException, IOException {
ftpClient = new FTPClient();
// org.apache.commons.net.MalformedServerReplyException: Could not parse response code.
// Server Reply: SSH-2.0-OpenSSH_7.2
// ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
// 设置以二进制方式传输
ftpClient.setDataTimeout(5000);
ftpClient.setConnectTimeout(connectTimeout);
ftpClient.setControlEncoding("UTF-8");
ftpClient.connect(host, port);
log.info("Connected to " + host + ".");
log.info("FTP server reply code:" + ftpClient.getReplyCode());
if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
if (ftpClient.login(user, password)) {
// Path is the sub-path of the FTP path
if (defaultPath != null && defaultPath.length() != 0) {
ftpClient.changeWorkingDirectory(defaultPath);
}
return true;
}
}
disconnect();
return false;
} public static File download(String remote, String local) throws IOException {
log.info("remote={},local={}", remote, local);
File downloadFile = null;
// 检查远程文件是否存在
FTPFile[] files = ftpClient.listFiles(remote);
if (files.length == 0) {
log.info("远程文件不存在: {}, {}", remote, files);
return downloadFile;
} File f = new File(local);
OutputStream out = null;
if (f.exists()) {
f.delete();
}
try {
//ftpClient.enterLocalPassiveMode();
out = new FileOutputStream(f);
boolean upNewStatus = ftpClient.retrieveFile(remote, out);
out.flush(); if (upNewStatus) {
downloadFile = f;
}
}
catch (Exception e) {
log.error(e.getMessage(), e);
}
finally {
if (out != null) {
out.close();
}
}
return downloadFile;
}
FTP需要在自己测试服务器开通21端口,这个已经叫运维开通了。且需要快钱把我们这边测试服务器ip加入快钱的白名单,否则是链接不到那边的FTP服务器的。
开始一直以为是快钱那边提供的用户是否需要什么文件连接权限,定位了很久的问题,最后搜索问题才发现对FTP连接模式和原理不清楚导致。
首先FTP分2中模式:主动模式(port)和被动模式(pasv).FTP标准命令TCP端口号为21,Port方式数据端口为20
不管哪种模式,都必须通过21这个端口建立起到FTP的管道连接,通过这个通道发送命令。
port模式:1.通过tcp的21端口建立起通道
2.客户端在此通道发起PORT命令,并产生一个随机非特殊的端口号N(1023<N<65536)给到FTP服务器。
3.此时客户端监听N+1端口(N+1>=1025,不一定是N端口+1),同时通过21的通道发送命令通知FTP服务器客户点通过此端口接受数据传输。
4.FTP服务器接收到上一步的响应后通过自己的数据源端口20,去链接远程的客户端的N+1端口(此时是FTP服务端主动发起的一个端口链接)
5.如果此时客户端的防火墙策略是不能随意外部链接内部服务器的端口,则会造成上一步出现数据端链接失败!
6.如果没有上一步的情况,FTP客户端则会接收到服务端响应并返回响应信息,则建立起了数据链接通道。
pasv模式:1.通过tcp的21端口建立起通道
2.但与主动方式的FTP不同,客户端不会提交PORT命令并允许服务器来回连它的数据端口,而是提交 PASV命令.会产生两个随机非特殊的端口N(1023<N<65536) 和N+1给到FTP服务器。其中N端口跟主动模式一样,会把N给到服务端的远程的21端口。相当于FTP服务端被动接受数据端口号而不是之前port模式的主动发起连接
3.FTP服务端会则会打开N+1的端口号
4.客户端发起N+1端口的链接,并建立数据链接。
port模式:
pasv模式:
上面的图都省略了建立tcp的21端口这个步骤。
正是因为之前采用主动模式,但是测试服务器防火墙阻止了快钱发起的数据端口的连接。也就是port模式的第5步出现问题。
因而FTPClient.listFiles(remote)或者FTPClient.retrieveFile(remote)方法时获取不了数据,就停止在那里,什么反应都没有,出现假死状态。
解决办法:在调用这两个方法之前,调用FTPClient.enterLocalPassiveMode();
这个方法的意思就是每次数据连接之前,ftp client告诉ftp server:数据连接的端口号已经告诉你了,你只需被动接受数据连接的请求就行
参考:http://www.cnblogs.com/xiaohh/p/4789813.html
http://blog.csdn.net/u010154760/article/details/45458219
FTP下载时连接正常获取不到数据的更多相关文章
- ftp 下载时防止从缓存中获取文件
//http://baike.baidu.com/link?url=QucJiA_Fg_-rJI9D4G4Z4687HG4CfhtmBUd5TlXrcWCeIEXCZxIh0TD7ng1wROAzAu ...
- RubyGem 下载时连接失败的解决方法
RubyGem 下载 gem 包失败,有一定原因是 https 导致的. 搜索了很久,找到一个解决的方法. 1.下载 cacert.pem,也就是 curl 的证书. http://curl.haxx ...
- http和ftp下载的区别
HTTP和FTP是两种网络传输协议的缩写,FTP是File Transportation Protocol(文件传输协议)的缩写,而HTTP则是Hyper Text Transportation Pr ...
- 速战速决 (6) - PHP: 获取 http 请求数据, 获取 get 数据 和 post 数据, json 字符串与对象之间的相互转换
[源码下载] 速战速决 (6) - PHP: 获取 http 请求数据, 获取 get 数据 和 post 数据, json 字符串与对象之间的相互转换 作者:webabcd 介绍速战速决 之 PHP ...
- .Net 连接FTP下载文件报错:System.InvalidOperationException: The requested FTP command is not supported when using HTTP proxy
系统环境: Windows + .Net Framework 4.0 问题描述: C#连接FTP下载文件时,在部分电脑上有异常报错,在一部分电脑上是正常的:异常报错的信息:System.Inval ...
- Java使用SFTP和FTP两种连接方式实现对服务器的上传下载 【我改】
[]如何区分是需要使用SFTP还是FTP? []我觉得: 1.看是否已知私钥. SFTP 和 FTP 最主要的区别就是 SFTP 有私钥,也就是在创建连接对象时,SFTP 除了用户名和密码外还需要知道 ...
- JDBC 连接mysql获取中文时的乱码问题
前段时间学习JDBC,要连接mysql获取数据.按照老师的样例数据,要存一些名字之类的信息,用的都是英文名,我当时就不太想用英文,就把我室友的名字存了进去,嘿嘿,结果,出问题了. 连接数据库语句: s ...
- ftp下载目录下所有文件及文件夹内(递归)
ftp下载目录下所有文件及文件夹内(递归) /// <summary> /// ftp文件上传.下载操作类 /// </summary> public class FTPH ...
- java ftp下载文件
1.使用官方正规的jar commons-net-1.4.1.jar jakarta-oro-2.0.8.jar 注意:使用ftp从windows服务器下载文件和从linux服务器下载文件不一样 2. ...
随机推荐
- UI设计|PS软件操作应用——GIF动图
前 言 JRedu 在之前的分享中,跟大家主要讲解了PS软件工具的基本操作,对主要的图层.蒙版.通道和滤镜都有一些介绍,希望对大家有所帮助,在介绍这些工具时也提到过GIF,而在本次分享中就跟大家 ...
- 关于php文件读取的一些学习记录
初学PHP的时候使用了一些文件读取API,但是没有真正弄清楚各API的区别以及差异,于是找了一篇学习了一下,贴在这里,引用自IBM社区的一篇文章, 整体整理测试如下 <?php /** * Cr ...
- 转每天一个linux命令(4):mkdir命令
linux mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录... 2.命令 ...
- Openfire分析之二:主干程序分析
引言 宇宙大爆炸,于是开始了万物生衍,从一个连人渣都还没有的时代,一步步进化到如今的花花世界. 然而沧海桑田,一百多亿年过去了-. 好复杂,但程序就简单多了,main()函数运行,敲个回车,一行Hel ...
- Django创建应用、模型、配置后台自动管理
1.创建应用 python manage.py startapp myblog 2.应用结构 3.创建模型(models.py) from django.db import models # Crea ...
- 粗略使用.NetCore2.0自带授权登陆Authorize
上篇有朋友提及到如果nginx做集群后应该还会有下一篇文章主讲session控制,一般来说就是登陆:本篇分享的内容不是关于分布式session内容,而是netcore自带的授权Authorize,Au ...
- MemCache在Windows环境下的搭建及启动
MemCache在Windows环境下的搭建及启动 一.memcache服务器端的安装 1.下载memcached的安装包,memcached_en32or64.zip,下载链接:http://pan ...
- 如何快速的理解JavaScript闭包?
先看问题 1. 在js中的作用域是什么? 作用域就是作用范围,作用空间.作用域分为全局作用域和局部作用域.(这个东西大家都明白) 如果把局部作用域比作一个国家,那么全局作用域就是地球,地球上除了那个国 ...
- ajax请求成功前loading
1.jquery方式 <!DOCTYPE html><html lang="en"><head> <meta charset=" ...
- 实现Spring RESTful服务的SSL
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt386 本文介绍如何让基于Spring的REST服务变得SSL/TSL化. 首 ...