0

我正在尝试使用 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 “Bigpathname”中的限定符超过 8 个字符

这真的很令人困惑,因为我可以使用 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. 感到非常困惑.. .

编辑十月 1 日下午 :)

好的,我终于让它在我的 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();
    }
}
4

4 回答 4

1

尝试使用路径的短名称。就像是/U/BIGPAT~1/XYZ/ABC/BIGPAT~1/BIGPAT~1/XYZ/ABC/MY_LOG.LOG

您可以使用 . 找到任何长度超过 8 个字符的目录的短名称dir /x

于 2012-09-28T20:21:14.603 回答
1

鉴于服务器实现的变化(和错误),FTP 客户端是出了名的难以编写。

我敢打赌,MVS 不完全支持sun.net.ftp.FtpClient,这是当您调用URL.openStreamFTP URL 时在后台使用的类。

Apache Commons Net 库应该支持 MVS,但听起来您已经找到了一个工作客户端。

于 2012-10-02T18:08:49.977 回答
1

在这种情况下,我认为问题也与服务器相关,它对我来说对 Filezilla 服务器来说一切正常,除非文件名长度(包括目录)超过 255 个字符,但是如果你想将 URL 类与另一个 FTP 一起使用,你必须覆盖或实现你自己的 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()); 
    ...

再见

**(犯错是人,宽恕是神)

于 2012-10-06T18:23:04.360 回答
0

您是否考虑过使用 RMI 来传输文件,您可以在不使用 ftp 的情况下将文件的直接路径作为参数提供,然后将文件以字节数组的形式发送回。

于 2012-10-05T23:13:49.373 回答