You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FTP下载时本地自动创建空文件及MLST类型转换异常求助

Java FTP下载:避免空文件+MLST类型转换问题解决

我来帮你搞定这两个FTP开发里的常见问题,都是踩过坑才知道的细节~


一、避免远程文件不存在时创建本地空文件

问题根源

你之前的代码之所以会生成空文件,是因为调用retrieveFile()时,本地输出流已经提前打开并创建了文件,哪怕远程文件不存在、下载失败,这个空文件也会留在本地。

解决思路:先验后下

正确的流程应该是:先检查远程文件是否存在,确认存在后再打开本地输出流执行下载。同时,为了应对下载中途失败的情况,还可以在下载失败后清理本地文件。

代码示例

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class FtpDownloadExample {
    public static void main(String[] args) {
        FTPClient ftpClient = new FTPClient();
        String server = "your-ftp-server.com";
        int port = 21;
        String user = "username";
        String pass = "password";
        String remoteFilePath = "/remote/path/your-file.txt";
        String localFilePath = "./local/your-file.txt";

        try {
            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            ftpClient.enterLocalPassiveMode(); // 被动模式,避免防火墙问题

            // 1. 先检查远程文件是否存在(用mlistFile高效查询单个文件)
            FTPFile remoteFile = ftpClient.mlistFile(remoteFilePath);
            if (remoteFile == null) {
                System.out.println("远程文件不存在,跳过下载");
                return;
            }

            // 2. 确认存在后,再打开本地输出流并执行下载
            File localFile = new File(localFilePath);
            try (OutputStream outputStream = new FileOutputStream(localFile)) {
                boolean downloadSuccess = ftpClient.retrieveFile(remoteFilePath, outputStream);
                if (downloadSuccess) {
                    System.out.println("文件下载成功!");
                } else {
                    // 下载失败(比如中途断开),删除本地空文件
                    if (localFile.exists()) {
                        localFile.delete();
                        System.out.println("下载失败,已清理本地空文件");
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭FTP连接
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

关键细节

  • 用mlistFile()替代listFiles():前者只查询单个文件的状态,比遍历整个目录高效得多;
  • 资源自动关闭:用try-with-resources确保输出流自动关闭;
  • 失败清理:即使下载中途出错,也能删除本地残留的空文件。

二、MLST命令的类型转换问题解决

问题分析

你遇到的类型转换问题,大概率是因为手动解析MLST响应字符串,或者错误地直接转换FTPFile的属性值。MLST返回的是键值对格式的字符串(比如modify=20240520143000;create=20240520100000;...),直接强转肯定会出错。

正确做法:用FTPClient封装的API处理

Apache Commons Net的FTPClient.mlistFile()方法已经帮你解析了MLST响应,返回的FTPFile对象包含了所有可用属性,直接调用方法或遍历属性即可。

代码示例:获取文件时间属性

FTPFile remoteFile = ftpClient.mlistFile(remoteFilePath);
if (remoteFile != null) {
    // 1. 获取最后修改时间(最可靠,几乎所有服务器都支持)
    long lastModifiedMillis = remoteFile.getTimestamp().getTimeInMillis();
    System.out.println("最后修改时间:" + new java.util.Date(lastModifiedMillis));

    // 2. 获取创建时间(注意:部分FTP服务器不支持create字段)
    for (String attribute : remoteFile.getAttributes()) {
        if (attribute.startsWith("create=")) {
            String createTimeStr = attribute.substring(7); // 截取"create="后面的时间字符串
            // 转换为Date对象,格式通常为YYYYMMDDHHMMSS
            java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
            try {
                java.util.Date createDate = sdf.parse(createTimeStr);
                System.out.println("创建时间:" + createDate);
            } catch (java.text.ParseException e) {
                System.out.println("解析创建时间失败:" + e.getMessage());
            }
            break;
        }
    }
}

兼容性处理

如果你的FTP服务器不支持MLST命令,可以先做兼容性检查:

if (ftpClient.hasFeature("MLST")) {
    // 使用MLST查询
    FTPFile remoteFile = ftpClient.mlistFile(remoteFilePath);
    // ... 处理逻辑
} else {
    // 降级使用传统方法,比如getModificationTime()
    String modifyTimeStr = ftpClient.getModificationTime(remoteFilePath);
    // 解析modifyTimeStr(格式通常为YYYYMMDDHHMMSS)
    // ...
}

内容的提问来源于stack exchange,提问作者User412387

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:09:07