我正在创建一个ApacheFTPS客户端(因为远程服务器不允许普通FTP)。我可以毫无问题地连接和删除文件,但在使用retrieveFile()或retrieveFileStream()时,它会挂起。
出于某种原因,非常小的文件确实会传输(高达5792字节),但其他任何东西都会给出以下PrintExpldListener输出:
运行:
220------欢迎使用纯FTPd[privsep][TLS]------
220您是允许的50个用户中的2个<当地时间现在是19:42。服务器端口:21
220这是一个专用系统-此服务器上也不欢迎匿名登录
220-IPv6连接
220您将在15分钟不活动后断开连接
验证TLS
234验证TLS正常
用户
331用户正常。需要密码
通过
230确定。当前受限目录为/
类型A
200类型现在为ASCII
EPSV
229扩展被动模式OK(| | | | 53360 |)
RETR测试。txt
150接受的数据连接
150 7.3 KB下载
代码如下:
try {
FTPSClient ftpClient = new FTPSClient("tls",false);
ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
ftpClient.connect(host, port);
int reply = ftpClient.getReplyCode();
if (FTPReply.isPositiveCompletion(reply)) {
ftpClient.enterLocalPassiveMode();
ftpClient.login(username, password);
ftpClient.enterLocalPassiveMode();
FileOutputStream outputStream = new FileOutputStream(tempfile);
ftpClient.setFileType(FTPClient.ASCII_FILE_TYPE);
ftpClient.retrieveFile("test.txt", outputStream);
outputStream.close();
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ioe) {
System.out.println("FTP client received network error");
}
任何想法都非常感谢。
希望几年后有人觉得我的评论有用。在我的例子中,我将retrieveFile
替换为retrieveFileStream
。它需要更多的代码,但至少可以工作。
即使以正确的顺序调用了PBSZ 0
和PROT P
,有时服务器确实需要SSL会话重用,而客户端默认情况下并非如此。
例如,当尝试列出目录时,会出现以下回复。因此,不会返回任何内容列表,这样客户端就会看到目录为空:
LIST /
150 Here comes the directory listing.
522 SSL connection failed; session reuse required: see require_ssl_reuse option in sftpd.conf man page
为了克服这一问题,需要通过重写\u prepareDataSocket()
方法对FTPSClient进行自定义初始化。
此处详细说明了解决方案:https://eng.wealthfront.com/2016/06/10/connecting-to-an-ftps-server-with-ssl-session-reuse-in-java-7-and-8/
从上述链接获取的工作代码示例:
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Locale;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import org.apache.commons.net.ftp.FTPSClient;
import com.google.common.base.Throwables;
public class SSLSessionReuseFTPSClient extends FTPSClient {
// adapted from: https://trac.cyberduck.io/changeset/10760
@Override
protected void _prepareDataSocket_(final Socket socket) throws IOException {
if(socket instanceof SSLSocket) {
final SSLSession session = ((SSLSocket) _socket_).getSession();
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method putMethod = cache.getClass().getDeclaredMethod("put",Object.class, Object.class);
putMethod.setAccessible(true);
final Method getHostMethod = socket.getClass().getDeclaredMethod("getHost");
getHostMethod.setAccessible(true);
Object host = getHostMethod.invoke(socket);
final String key = String.format("%s:%s", host, String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT);
putMethod.invoke(cache, key, session);
} catch(Exception e) {
throw Throwables.propagate(e);
}
}
}
}
通常,FTPS连接的FTP命令顺序是(根据RFC 4217)AUTH TLS
,PBSZ 0
,然后是USER
,PASS
,等等。因此,您可以尝试:
FTPSClient ftpClient = new FTPSClient("tls",false);
ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
ftpClient.connect(host, port);
int reply = ftpClient.getReplyCode();
if (FTPReply.isPositiveCompletion(reply)) {
ftpClient.execPBSZ(0);
reply = ftpClient.getReplyCode();
// Check for PBSZ error responses...
ftpClient.execPROT("P");
reply = ftpClient.getReplyCode();
// Check for PROT error responses...
ftpClient.enterLocalPassiveMode();
这明确地告诉服务器不要缓冲数据连接(PBSZ 0
),并使用TLS保护数据传输(PROT P
)。
您能够传输一些字节的事实表明,该问题不是防火墙/路由器/NAT的常见复杂性,这是另一个常见的FTPS问题。
希望这能有所帮助!
我目前正在创建一个基于此小提琴的动态下拉列表 除了我试图调用JSON文件之外,我一直在跟进。我的代码如下: ]; 范围metro可以工作,但是当连接到JSON文件时,其余的就不能工作了。我假设它会工作,因为它实际上是相同的结构。我做错了什么? [编辑] 正如你们中的一些人所回答的那样,在我进行上述操作之前,我最初尝试了这种http注入: 这不起作用,所以我试了另一种方法。所以我假设它与JSON赋值
A Freudian slip is when you say one thing, but mean your mother. — Anon 我们每个人都会犯错误,这就是为什么通常铅笔上会配有橡皮擦的原因。 每当 Puppet 客户端在改变一个文件时,就会将改变前的版本做个备份。 如果在 Puppet 客户端上对一个已经存在的文件做修改,不管多小的改变, 我们都可以看到这一过程: # puppe
使用Apache Commons FTPSClient,下载的文件始终存储为0字节。我尝试了不同的方法,但在存储的文件中总是得到0字节。在下面的代码中,我展示了这三种方法。 以下是使用的代码:
问题内容: 我有一个第三方表单解决方案,可以通过导入javascript文件将其嵌入到我的网站中。嵌入脚本的说明实际上与“复制并粘贴以下内容”类似: 看一下实际的javascript文件,它基本上只是一组 现在,我尝试了几件事…我有一个带有模板URL的指令,该指令命中包含该脚本的简单部分。看起来像这样: 指示: form.html 发生的一切只是呈现了html,但脚本的内容却没有… 我尝试了一个请
我想从图中所示的.jar文件中检索compare.ecore模型。 我试图在Eclipse IDE中复制并粘贴它,但没有成功。我用WinRAR打开了给定路径中的.jar文件,但在归档中找不到模型。 如何检索此模型?
我使用Apache IO FTPSClient在FTPS服务器上放置文档时遇到问题。我能够连接到服务器。我的状态很好(返回211)。如果我要求一个目录列表,我得到空。 我没有看到任何错误。我可以通过FileZilla连接到服务器。它在TLS上使用显式FTP。 感谢任何帮助。