FTP异常501“路径名”超过8个字符

时间:2012-09-28 18:20:12

标签: java url ftp uri mvs

我正在尝试使用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();
    }
}

4 个答案:

答案 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的情况下将文件作为参数提供直接路径,然后将文件以字节数组的形式发回。