我正在尝试使用FTP协议通过URI访问文件。出于明显的安全原因,我不得不做出一些改变,但这就是问题似乎来自的地方。
我的URI如下:
ftp://user:pasword@host.net/u/Bigpathname/XYZ/ABC/BigPathname/bigpathname/xyz/abc/MY_LOG.LOG
我看到了这个例外:
sun.net.ftp.FtpProtocolException: CWD Bigpathname:501 A qualifier in "Bigpathname" is more than 8 characters
这实在令人困惑,因为我可以使用CD命令从Windows 7命令行访问该文件。一次一个目录和一个完整路径。
我发现有一篇文章提到MVS文件名必须是8个或更少的字符,但这并不能解释我如何从命令行获取这些相同的文件!它们确实存在,那里有我可以下载手册的数据,但我无法通过Java中的URI实现。
PS我使用.toURL()。openStream()来获取本地机器上的文件就好了,只有当我尝试从我的服务器上获取文件时它才会失败。
10月1日编辑
我可以使用FileZilla和Windows 7命令行中的基本FTP客户端访问MVS主机上的文件 - 但我仍然无法从URI / URL获取它们。我下载了一个非常基本的Java构建的FTP客户端,并尝试从那里访问我的程序中的相同文件,路径工作,但因为我的文件名中有一个点“MY_LOG.LOG”我得到File does not exist 501 Invalid data set name "MY_LOG.LOG". Use MVS Dsname conventions.
我完全对此感到困惑......
编辑Ocotober第一天下午:)
好的我终于可以在我的Java代码中使用FTP客户端了 - 但我仍然想使用URL类,因为我在本地和远程机器上都有日志。有没有办法对URL字符串进行编码,以便它可以使用FTP协议从远程计算机检索文件?我不确定它在Java URL类中如何工作,但在FTP客户端我不得不使用CWD然后使用RETR命令。
如果我能做到这一点,那么我有一个获取所有日志的解决方案,否则我将不得不检测它是文件还是ftp URL然后表现不同。不是世界末日而是我想要的......
尝试仅使用URL获取文件的代码如下:( sysc是有效的主机)
void testFTP()
{
String ftp = "ftp://user:pword@sysc/u/Xxxxxxxxxx/ICS/YT7/XxxxxXxxxxxxx/xxxxxxxxx/logs/xxxxxxxx/XX_YT.LOG";
try
{
URI uri = new URI(ftp);
URL ftpFile = uri.toURL();
BufferedReader in = new BufferedReader(new InputStreamReader(ftpFile.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
答案 0 :(得分:1)
尝试使用路径的短名称。像/U/BIGPAT~1/XYZ/ABC/BIGPAT~1/BIGPAT~1/XYZ/ABC/MY_LOG.LOG
您可以使用dir /x
找到长度超过8个字符的任何目录的简称。
答案 1 :(得分:1)
鉴于服务器实现的变化(和错误),FTP客户端很难编写。
我认为sun.net.ftp.FtpClient
并不完全支持MVS,这是在FTP URL上调用URL.openStream
时使用的类。
Apache Commons Net library应该支持MVS,但听起来你已经找到了一个有效的客户端。
答案 2 :(得分:1)
在这种情况下,我认为问题也是服务器相关的,除了当文件名长度(包括目录)超过255个字符,但是如果你想将URL类与另一个FTP一起使用,它对Filezilla Server一切正常。覆盖或实现自己的URLStreamHandlerFactory。
URL.setURLStreamHandlerFactory(...);
我没有找到任何我最喜欢的java FTP客户端女巫是Apache,所以我开发了一个,但可能需要一些修饰。
package net.custom.streamhandler.apacheftp;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
public class ApacheURLStreamHandlerFactory implements URLStreamHandlerFactory {
public URLStreamHandler createURLStreamHandler(String protocol) {
//this will only override the chosen protocol
if ( protocol.equalsIgnoreCase("ftp") )
return new CustomHandler();
else
return null;
}
}
class CustomHandler extends URLStreamHandler {
protected URLConnection openConnection(URL url)
throws IOException {
return new CustomURLConnection(url);
}
}
class CustomURLConnection extends URLConnection {
int reply;
FTPClient ftp = new FTPClient();
InputStream in;
static int defaultPort = 21;
static String defaultPath = "/";
CustomURLConnection ( URL url)
throws IOException {
super( url );
}
synchronized public void connect() throws IOException {
try {
int port;
if ((port = url.getPort()) == -1 )
port = defaultPort;
ftp.connect(url.getHost(), port);
String login = "anonymous";
String password = "";
if(url.getAuthority().indexOf(':')>-1 &&
url.getAuthority().indexOf('@')>-1){
String []auxArray = url.getAuthority().replaceAll("@", ":").split(":");
login = auxArray[0];
password = auxArray[1];
}
ftp.login(login, password);
reply = ftp.getReplyCode();
if (FTPReply.isPositiveCompletion(reply)) {
System.out.println("Connected Apache Success");
} else {
System.out.println("Connection Apache Failed");
ftp.disconnect();
}
in = ftp.retrieveFileStream(url.getFile());
} catch (SocketException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
connected = true;
}
synchronized public InputStream getInputStream()
throws IOException {
if (!connected)
connect();
return ( in );
}
}
*请记住,您可以通过这种方式实现处理java.net.URL的不同协议的新方法。
您的代码......
...
{
String ftp = "ftp://user:pword@sysc/u/Xxxxxxxxxx/ICS/YT7/XxxxxXxxxxxxx/xxxxxxxxx/logs/xxxxxxxx/XX_YT.LOG";
try
{
URL.setURLStreamHandlerFactory(new ApacheURLStreamHandlerFactory());
...
G'Bye
**(错误是人,原谅是神圣的)
答案 3 :(得分:0)
您是否考虑过使用RMI来传输文件,这样您就可以在不使用ftp的情况下将文件作为参数提供直接路径,然后将文件以字节数组的形式发回。