0

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コマンドラインからファイルにアクセスできるため、これは本当に混乱します。一度に 1 つのディレクトリとフル パスの両方。

MVS ファイル名は 8 文字以下でなければならないという記事を見つけましたが、コマンド ラインからこれらの同じファイルにアクセスする方法が説明されていません。それらは存在しますが、マニュアルをダウンロードできるデータがありますが、Java の URI 経由ではそこにアクセスできません。

PS .toURL().openStream() を使用して、ローカル マシン上のファイルを正常に取得します。サーバーからファイルを取得しようとすると失敗します。

10月1日編集

Windows 7 コマンド ラインから FileZilla と基本的な 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. これに完全に困惑しています.. .

10月1日の午後を編集:)

ようやく Java コードで FTP クライアントを使用できるようになりましたが、ローカル マシンとリモート マシンの両方にログがあるため、引き続き URL クラスを使用したいと考えています。FTP プロトコルを使用してリモート マシンからファイルを取得できるように、URL 文字列をエンコードする方法はありますか? Java URL クラスでどのように機能するかはわかりませんが、FTP クライアントでは CWD を使用してから RETR コマンドを使用する必要がありました。

これができれば、すべてのログを取得するための 1 つの解決策が得られます。それ以外の場合は、それがファイル URL なのか 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

4 に答える 4

1

FTP クライアントは、サーバー実装のバリエーション (およびバグ) を考慮すると、作成が難しいことで有名です。

MVS は、FTP URLsun.net.ftp.FtpClientを呼び出すときに内部で使用されるクラスであるによって完全にサポートされているわけではありません。URL.openStream

Apache Commons Net ライブラリはMVS をサポートする必要がありますが、動作するクライアントが既に見つかっているようです。

于 2012-10-02T18:08:49.977 に答える
1

この場合、問題はサーバーにも関連していると思います。ファイル名の長さ (ディレクトリを含む) が 255 文字を超える場合を除いて、Filezilla サーバーではすべて正常に動作しますが、別の FTP で URL クラスを使用する場合は、オーバーライドまたは実装する必要があります。独自の 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()); 
    ...

さようなら

**(過ちを犯すのは人間、許すのは神)

于 2012-10-06T18:23:04.360 に答える
1

パスの短い名前を使用してみてください。何かのようなもの/U/BIGPAT~1/XYZ/ABC/BIGPAT~1/BIGPAT~1/XYZ/ABC/MY_LOG.LOG

8 文字を超えるディレクトリの短縮名は、dir /x.

于 2012-09-28T20:21:14.603 に答える
0

ftpを使用せずにファイルへの直接パスをパラメータとして指定し、ファイルをバイト配列で送り返すことができるように、ファイルを転送するためにRMIを使用することを検討しましたか。

于 2012-10-05T23:13:49.373 に答える