FTP исключение 501 "путь" более 8 символов

Я пытаюсь получить доступ к файлу через URI, используя протокол FTP. По очевидным соображениям безопасности мне пришлось внести некоторые изменения, но именно отсюда возникли проблемы.

Мой 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 символов

Это действительно сбивает с толку, так как я могу получить доступ к файлу из командной строки Windows 7 с помощью команды CD просто отлично. И один каталог за раз и полный путь.

Я нашел одну статью, в которой упоминалось, что имена файлов MVS должны содержать не более 8 символов, но это не объясняет, как я могу получить эти же файлы из командной строки! Они существуют, там есть данные, которые я могу скачать, но не могу получить их через URI в Java.

PS Я использую.toURL(). OpenStream(), чтобы получить файлы на моем локальном компьютере очень хорошо, это происходит только когда я пытаюсь получить их с моего сервера.

РЕДАКТИРОВАТЬ 1 октября

Я могу получить доступ к файлам на хосте MVS, используя FileZilla и базовый FTP-клиент из командной строки Windows 7 - но я все еще не могу получить их по URI/URL. Я загрузил очень простой встроенный Java-клиент на Java и попытался оттуда получить доступ к тому же файлу в моей программе, и путь работает, но поскольку в имени моего файла есть точка "MY_LOG.LOG", я получаю File does not exist 501 Invalid data set name "MY_LOG.LOG". Use MVS Dsname conventions. Я совершенно озадачен этим...

РЕДАКТИРОВАТЬ Ocotober 1-й день:)

ОК, я наконец-то заставил его работать с FTP-клиентом в своем Java-коде - но я все еще хочу использовать класс URL, так как у меня есть журналы как на локальных, так и на удаленных машинах. Есть ли способ кодировать строку URL, чтобы он мог получить файл с удаленного компьютера по протоколу FTP? Я не уверен, как это работает в классе Java URL, но в клиенте FTP мне пришлось использовать CWD, а затем команду RETR.

Если я смогу сделать это, у меня будет одно решение для получения всех моих журналов, в противном случае мне придется определить, является ли это URL-адрес файла или ftp, а затем вести себя по-другому. Не конец света, но не то, что я хочу...

Код, который пытается получить файл только с помощью 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 ответа

Решение

В этом случае я думаю, что проблема также связана с сервером, у меня все хорошо работает с Filezilla Server, за исключением случаев, когда длина имени файла (включая каталоги) превышает 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()); 
    ...

G'Bye

** (Человеку свойственно ошибаться, Богу прощать)

Попробуйте использовать короткое имя для пути. Что-то вроде /U/BIGPAT~1/XYZ/ABC/BIGPAT~1/BIGPAT~1/XYZ/ABC/MY_LOG.LOG

Вы можете найти короткое имя для любого каталога длиннее 8 символов с dir /x,

FTP-клиенты общеизвестно трудны для написания, учитывая вариации (и ошибки) серверных реализаций.

Держу пари, что MVS не полностью поддерживается sun.net.ftp.FtpClient, который является классом, используемым под капотом, когда вы звоните URL.openStream на FTP-URL.

Библиотека Apache Commons Net должна поддерживать MVS, но, похоже, вы уже нашли работающий клиент.

Рассматривали ли вы использование RMI для передачи файлов таким образом, чтобы можно было указать прямой путь к файлу в качестве параметра без использования ftp, а затем отправить файл обратно в байтовый массив.

Другие вопросы по тегам