【问题标题】:Can't transfer a file with a binary transfer with a FTP client无法使用 FTP 客户端通过二进制传输传输文件
【发布时间】:2015-04-14 21:20:58
【问题描述】:

有这个 FTP 客户端,我用字节数组传输文件。在控制台中显示成功传输但它没有传输任何内容,我收到以下错误:

Exception in thread "main" java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at ftp.ftp.connect(ftp.java:110)
at ftp.test.main(test.java:12)

我希望将文件传输到此文件路径:c:/Users/username/Desktop/FTP

这是我的程序:

package ftp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;

public class ftp
{
public synchronized void connect(String host, int port, String user,
        String pass) throws IOException {
    Socket socket = new Socket(host, port);
    //  if (socket != null) {
    //     throw new IOException("SimpleFTP is already connected. Disconnect first.");
    //   }
    //  socket = new Socket(host, port);
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    BufferedWriter writer = new BufferedWriter(
            new OutputStreamWriter(socket.getOutputStream()));


    String response = reader.readLine();

    if (!response.startsWith("220-")) {
        throw new IOException(
                "FTP modtog et ukendt svar, da den blev forbundet til FTP server: "
                        + response);
    } else {System.out.println("1:"+response);
    response = reader.readLine();
    System.out.println("1:"+response);
    response = reader.readLine();
    System.out.println("1:"+response);


    }
    writer.write("user geek"+"\r\n");
    writer.flush();
    response= reader.readLine();
    System.out.println("2"+response);
    // response = reader.readLine();
    /*  if (!response.startsWith("331 ")) {
          throw new IOException(
              "SimpleFTP received an unknown response after sending the user: "
                  + response);
        }
        else {*/
    writer.write("PASS hello" +"\r\n");
    writer.flush();
    response= reader.readLine();
    System.out.println("3"+response);
    //}


    //response = reader.readLine();
    /*if (!response.startsWith("230 ")) {
          throw new IOException(
              "SimpleFTP was unable to log in with the supplied password: "
                  + response);
        }
        else {*/
    //System.out.println("4"+response);
    //}

    writer.write("pasv"+"\r\n");
    writer.flush();
    response= reader.readLine();
    System.out.println("5"+response );
    String [] r=response.trim().split(",");

    String reg=r[4];
    String add= r[5].replace(")", "");
    int m = Integer.parseInt(reg);
    int a = Integer.parseInt(add);

    int port1 = m*256+a;
    System.out.println(port1);
    Socket datasocket = new Socket("127.0.0.1", port1);
    writer.write("type A\r\n");
    writer.flush();
    response= reader.readLine();
    System.out.println("6"+response);
    BufferedReader reader2 = new BufferedReader(new InputStreamReader(datasocket.getInputStream()));


    writer.write("LIST\r\n");
    writer.flush();
    response= reader.readLine();
    System.out.println("7"+response);


    String text;
    while((text =reader2.readLine())!=null){
        System.out.println(text);

        writer.write("RETR\r\n");
        writer.flush();
        response= reader.readLine();
        System.out.println("8"+response);

        Socket filsocket = new Socket ("localhost", port1);
        InputStream is = null;
        FileOutputStream fos = null;

        byte[] mybytearray = new byte[1024];
        try {
            is = filsocket.getInputStream();
            fos = new FileOutputStream("myfile.txt");

            int count;
            while ((count = is.read(mybytearray)) >= 0) {
                fos.write(mybytearray, 0, count);
            }
        } finally {
            fos.close();
            is.close();
            filsocket.close();
        }

    }


}       

}

输出:

1:220-FileZilla Server version 0.9.50 beta
1:220-written by Tim Kosse (tim.kosse@filezilla-project.org)
1:220 Please visit https://filezilla-project.org/
2331 Password required for geek
3230 Logged on
5227 Entering Passive Mode (127,0,0,1,219,100)
6200 Type set to A
7150 Opening data channel for directory listing of "/"
-rw-r--r-- 1 ftp ftp              0 Apr 14 20:18 abc.txt
8226 Successfully transferred "/"
Exception in thread "main" java.net.ConnectException: Connection refused:   connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at ftp.ftp.connect(ftp.java:112)
at ftp.test.main(test.java:12)

【问题讨论】:

    标签: java ftp


    【解决方案1】:

    好的。这里有很多问题需要解决。首先,每次您需要通过数据通道获取数据(使用您从被动响应计算的任意高端口)时,您需要发出另一个 PASV 命令并使用该新端口打开一个新套接字。

    试试这个,代码,从 LIST 命令开始:

    writer.write("LIST\r\n");
    writer.flush();
    response = reader.readLine();
    System.out.println("7" + response);
    
    List<String> files = new ArrayList<>();
    String text;
    while ((text = reader2.readLine()) != null) {
        String filename = parseFilename(text);
        files.add(filename);
    }
    reader2.close();
    datasocket.close();
    reader.readLine();
    
    for (String file : files) {
        int passivePort = getPort(reader, writer);
        writer.write("RETR test.txt\r\n");
        writer.flush();
        System.out.println(response);
         byte[] mybytearray = new byte[1024];
        // try-with-resources
        try (Socket filesocket = new Socket("localhost", passivePort);
             InputStream is = filesocket.getInputStream();
             FileOutputStream fos = new FileOutputStream("c:\\temp\\" + file)) {
             int count;
             while ((count = is.read(mybytearray)) >= 0) {
                 fos.write(mybytearray, 0, count);
             }
        }
    }
    

    getPort 那么当然是这样的:

    private int getPort(BufferedReader reader, BufferedWriter writer) throws IOException {
        String response;
        writer.write("PASV" + "\r\n");
        writer.flush();
        response = reader.readLine();
        System.out.println("5" + response);
        String[] r = response.trim().split(",");
    
        String reg = r[4];
        String add = r[5].replace(")", "");
        int m = Integer.parseInt(reg);
        int a = Integer.parseInt(add);
    
        return m * 256 + a;
    }
    

    我会让你写 parseFilename;这只是从服务器返回的原始列表中提取文件名的问题。

    这段代码应该可以为您解决问题,并且可以针对本地 Apache FTP 服务器为我工作。由于您使用的是 Filezilla,因此如果他们返回的数据比我的服务器多,您可能需要在某处多读一行 - 但否则这应该适合您。

    【讨论】:

    • 好的,发现另一个问题...确保你有 RETR 命令的文件名。应该是这样的: writer.write("RETR abc.txt\r\n");完成后,您要坚持使用第一个 localhost 套接字来读取文件。
    • 但是我只传输 abc.txt 而不是任何文件。我想传输任何文件不仅是 abc.txt
    • 我收到一个错误:Socket filsocket = new Socket ("localhost", port1);
    • 在获取文件列表后尝试关闭“datasocket”套接字。当另一个套接字仍然打开时,您将无法初始化 filsocket。
    • 至于传输所有文件:FTP 并不是这样工作的。命令行客户端通常支持“MGET”命令,但客户端仍然需要读取文件列表并对每个文件执行单独的 RETR 命令。完成这项工作后,您需要解析文件夹中的文件列表并为每个文件执行单独的 RETR。
    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 2012-02-07
    • 2010-12-26
    • 2017-09-25
    • 2023-04-07
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多