【问题标题】:FTP exception 501 "pathname" more than 8 charactersFTP 异常 501 “路径名”超过 8 个字符
【发布时间】:2012-09-28 18:20:12
【问题描述】:

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

【问题讨论】:

  • 它可以特定于您的服务器吗?您可以使用一些 FTP 客户端进行检查。
  • 您能发布您正在使用的(匿名)代码吗?您没有在路径参数中包含用户名和密码,是吗?

标签: java url ftp uri mvs


【解决方案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()); 
    ...

再见

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

【讨论】:

  • 我如何恢复到非 ftp 协议的默认 URLStreamHandler?一些日志文件存在于我的本地计算机上,我通过文件 URL 引用它们。
  • createURLStreamHandler(String protocol) 具有您要添加或覆盖的协议。您可以创建一个名为“file”或“resource”的新方法 connect 方法包含返回 InputStream 所需的所有代码。创建一个新的来处理文件。或者在示例中添加通过 InputStream 加载文件的功能,以防文件位于本地目录中。 *您可能需要设置/检测您的本地 IP,以防您想要本地/和 ftp 的 ftp 协议。
  • 感谢您的所有帮助和努力。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 有什么办法可以配置或者替换sun客户端,让URL类使用一个可以工作的ftp客户端?那值 200 分 :)
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-17
      • 2018-07-02
      • 1970-01-01
      相关资源
      最近更新 更多