【问题标题】:Why does the FTP download not work properly with Java为什么 FTP 下载无法使用 Java 正常工作
【发布时间】:2020-02-08 11:29:34
【问题描述】:

我目前正在使用 Java 开发一个小型清单生成器程序。我想将创建的文件上传并下载到我的 FTP 服务器 (ftps)。我正在使用以下代码进行下载:

public static void downloadfile(){
    FTPSClient con = null;

    System.out.println("Download Status: 5%");
    try
    {
        System.out.println("Download Status: 20%");
        con = new FTPSClient();
        con.connect(url);

        if (con.login(user, psw))
        {
            System.out.println("Download Status: 50%");
            con.enterLocalPassiveMode(); // important!
            con.setFileType(FTP.BINARY_FILE_TYPE);
            String data = "E:\\Downloads\\Testdokument.txt";

            OutputStream out = new FileOutputStream(new File(data));
            boolean result = con.retrieveFile("Testdokument.txt", out);
            out.close();
            System.out.println(result);
            if (result) {
                System.out.println("Download Status: 100%");
            } else if(result == false) {
                System.out.println("Download won't work");
            }
            con.logout();
            con.disconnect();
        }
    }
    catch (Exception e)
    {
        System.out.println("download failed");
        e.printStackTrace();
    }

}

问题是下载本身工作正常。但是下载的文件是空的。如果我用图像尝试它不是“可读的”。相反,上传工作完美。我使用 Apache Common IO Library 来实现 FTP 功能。

如果我下载文件,控制台会显示第一个状态 5%、20%、50%,然后添加错误语句后,下载将无法工作...

我不知道为什么文件本身正在下载但不包含任何内容。

有什么想法吗?

【问题讨论】:

  • 本地数据文件是否存在?父目录存在吗?

标签: java file download ftp is-empty


【解决方案1】:

你没有正确地在 java 中做资源。

任何时候你创建一个代表资源的对象,你都必须关闭它。你打开一个新的FileOutputStream,这是一个资源。任何实现AutoCloseable 的东西绝对是你必须关闭的资源。试试这个:

try (OutputStream out = new FileOutputStream(data /* no need to wrap in File */)) {
    // do your stuff with out here
}

第二点:你的异常处理很糟糕;请停止犯这个常见的错误。异常包含 4 个有用的信息位:类型、消息、跟踪和原因。您实际上是在将 4 个中的 3 个扔进垃圾箱。只需将 throws Exception 添加到您的 main 方法和您的 downloadFile 方法中。它可以节省您的打字时间,并使您的错误消息更加有用。

【讨论】:

  • e.printStackTrace() 输出所有 4 条信息。
  • @rzwitserloot 感谢您的回答。我就是这样学的。但我会记住你的提示并尝试优化我的代码。
  • @Stefan 不,它没有。因此名称为“打印堆栈跟踪”:它仅打印堆栈跟踪。
  • printStartTrace 输出所有信息,见这个:java.lang.Exception: something bad happened at com.company.Main.doSomething(Main.java:14) at com.company.Main.main(Main.java:22) Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at com.company.Main.doSomething(Main.java:10) ... 1 more 抱歉,格式丑陋,我不知道如何在 cmets 中格式化此类文本。
  • @Stefan 这只是错误的。您显示的不是命令e.printStackTrace() 的输出。
【解决方案2】:

我找到了解决办法。

我添加了以下两件事,现在可以使用了

con.execPBSZ(0);
con.execPROT("P");

不知道那代表什么,但我会找出来的。

【讨论】:

    【解决方案3】:

    我知道这个答案是题外话,但我想为用户 rzwitserloot 提供一个示例,它表明 printStackTrace() 没有隐藏任何重要信息。这不适合评论:

    public class Main
    {
    
        public static void doSomething()
        {
            int array[] = {1, 2, 3};
            int b = array[3];  // throws Exception
        }
    
        public static void test() throws Exception
        {
            try
            {
                doSomething();
            }
            catch (Exception e)
            {
                throw new Exception("something bad happened", e);
            }
        }
    
        public static void main(String[] args) throws Exception
        {
            try
            {
                test();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    

    产生输出:

    java.lang.Exception: something bad happened
        at Main.test(Main.java:18)
        at Main.main(Main.java:26)
    Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
        at Main.doSomething(Main.java:7)
        at Main.test(Main.java:14)
        ... 1 more
    

    另请参阅 Oracle 的文档:

    【讨论】:

    • 代码 'e.printStackTrace()' 不在您的 sn-p 中。我们达成了强烈的一致意见:我说过要做你所做的。
    • 哦,对不起。我发送了错误的示例。我会解决这个问题...完成。
    猜你喜欢
    • 2011-07-24
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多