2012-09-28 54 views
0

我試圖通過使用FTP協議的URI訪問文件。出於明顯的安全原因,我不得不做出一些改變,但這是問題似乎來自的地方。FTP異常501「路徑名」超過8個字符

我的URI如下: ftp://user:[email protected]/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到達那裏。我使用.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 1日下午:)

OK我終於得到它在我的Java代碼與一個FTP客戶端的工作 - 但我仍想使用URL類,因爲我有兩個本地日誌和遠程機器。有沒有辦法對URL字符串進行編碼,以便它可以通過FTP協議從遠程計算機檢索文件?我不確定它如何在Java URL類中工作,但在FTP客戶端中,我必須使用CWD,然後使用RETR命令。

如果我可以做到這一點,那麼我有一個解決方案來獲取我所有的日誌,否則我將不得不檢測它是一個文件或ftp URL,然後表現不同。世界上沒有結束,但不是我想要的......

,試圖獲得該文件只是一個URL的代碼如下:(SYSC是一個有效的主機)

void testFTP() 
{ 
    String ftp = "ftp://user:[email protected]/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(); 
    } 
} 
+1

能不能具體到你的服務器?您可以使用某個FTP客戶端進行檢查。 –

+0

您可以發佈您正在使用的(匿名)代碼嗎?您沒有在路徑參數中包含用戶名和密碼,對嗎? –

回答

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:[email protected]/u/Xxxxxxxxxx/ICS/YT7/XxxxxXxxxxxxx/xxxxxxxxx/logs/xxxxxxxx/XX_YT.LOG";  
    try 
    { 
     URL.setURLStreamHandlerFactory(new ApacheURLStreamHandlerFactory()); 
    ... 

G'Bye

**(犯錯是人之常情,寬恕是超凡)

+0

我怎麼會恢復到默認的URLStreamHandler非FTP協議?一些日誌文件存在於本地機器上,我通過文件URL來引用它們。 – BigMac66

+0

createURLStreamHandler(String protocol)具有要添加或覆蓋的協議。你可以創建一個新的名爲「文件」或「資源」 的連接方法的所有返回的InputStream所需的代碼。創建一個新文件來處理文件。或者在示例中添加該功能以通過InputStream加載文件,以防文件位於本地目錄中。 *您可能需要設置/檢測你的本地IP是你想你的本地/ FTP和FTP協議的情況下什麼。 – PbxMan

+0

感謝您的幫助和努力。 – BigMac66

1

嘗試使用路徑的簡稱。類似於/U/BIGPAT~1/XYZ/ABC/BIGPAT~1/BIGPAT~1/XYZ/ABC/MY_LOG.LOG

您可以使用dir /x查找長度超過8個字符的任何目錄的短名稱。

1

鑑於服務器實現(和錯誤)的變化,FTP客戶端非常難以編寫。

我敢打賭,MVS並不完全支持sun.net.ftp.FtpClient,這是在FTP URL上調用URL.openStream時引擎蓋下的類。

Apache Commons Net library應該支持MVS,但它聽起來像你已經找到了一個工作的客戶端。

+0

有什麼辦法來配置Sun客戶端或更換,以使URL類將使用一個FTP客戶端軟件的工作原理?這將是值得的200點:) – BigMac66

0

你有沒有使用RMI運輸方式,您可以給文件作爲參數的直接路徑的文件,而無需使用FTP,然後在文件中都有一個字節數組送回考慮。

相關問題