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, а затем отправить файл обратно в байтовый массив.