惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
月光博客
月光博客
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
小众软件
小众软件
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
博客园 - 三生石上(FineUI控件)
A
About on SuperTechFans
J
Java Code Geeks
云风的 BLOG
云风的 BLOG
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
IT之家
IT之家
Vercel News
Vercel News
量子位
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
腾讯CDC
有赞技术团队
有赞技术团队

博客园 - 海乐学习

VS2026创建.net8的控制台程序并能在银河麒麟V10的Liunx上运行 在麒麟系统中卸载RabbitMQ Java Maven 开发的常用命令 C语言开发的常用命令 三汇Linux配置Config说明 Java实现优雅的关闭程序并执行清理流程的写法 C语言开发中优雅的关闭程序并执行清理流程的写法 将C语言开发的程序做成 麒麟系统的服务(Systemd 标准服务,Linux 通用) 实现开机自启动 ZeroMQ的DEALER双帧结构(路由空帧 + 业务帧)(支持异步收发、主动推送事件)C写服务端 java写客户端 ZeroMQ中ZMQ_DEALER单帧数据(支持异步收发、主动推送事件)C写服务端 java写客户端 win10系统中 关闭专注助手 执行 xx.sh 脚本文件时出现: /bin/bash^M:解释器错误: 没有那个文件或目录 运行编译打包好的 xxx.jar 中没有主清单属性 出现这个错误 将Java编译的 .jar文件做成 麒麟系统的服务(Systemd 标准服务,Linux 通用) 实现开机自启动 将Java编译的 .jar文件做成windows服务 实现开机自启动 方法二 RabbitMQ在麒麟系统中离线安装说明 VMware启动虚似机后出现 无法获取快照信息: 锁定文件失败 模块“Snapshot”启动失败。未能启动虚拟机。 C语言在Linux中开发完整Demo包含读配置文件写日志和定时器Timer C语言在Linux中开发读取配置文件app.conf 麒麟V10 Server系统中搭建C语言开发环境 麒麟ServerV10 修改IP4地址 麒麟ServerV10 配置IP4 当系统中有两个版本的Maven时,用IDEA创建Maven有时会出错 麒麟ServerV10安装 espeak-ng 和 ffmpeg 方法 C语言在Linux中开发没有界面纯后台运行的Demo程序(含日志和Timer) C语言在Linux中开发使用定时器Timer在界面上显示时间 C语言在Linux中开发带界面的程序(含每小时日志) C语言在Linux中开发第一个项目Hello Word 在apache-maven项目中使用log4写日志 在apache-maven项目中解决中文乱码问题
java实现ftp上传
海乐学习 · 2026-01-13 · via 博客园 - 海乐学习

java  maven 实现 ftp 上传

pom.xml

    <!-- Apache Commons Net 用于 FTP 操作 -->
    <dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>3.9.0</version>
    </dependency>

FtpUploader.java

package com.JoinCallCCVoxGuide;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
 

public class FtpUploader {
    protected static final Logger logger = LoggerFactory.getLogger(FtpUploader.class);

    private String server;
    private int port;
    private String username;
    private String password;
    private FTPClient ftpClient;

    /**
     * 构造函数
     * @param server FTP服务器地址
     * @param port FTP端口(默认21)
     * @param username 用户名
     * @param password 密码
     */
    public FtpUploader(String server, int port, String username, String password) {
        this.server = cleanServerAddress(server);  // 清理地址
        this.port = port;
        this.username = username;
        this.password = password;
        this.ftpClient = new FTPClient();
    }

    /**
     * 清理FTP服务器地址
     * 移除 ftp://, ftps:// 等协议前缀
     */
    private String cleanServerAddress(String server) {
        if (server == null || server.isEmpty()) {
            return server;
        }

        // 转换为小写,统一处理
        String cleaned = server.toLowerCase();

        // 移除协议前缀
        if (cleaned.startsWith("ftp://")) {
            cleaned = cleaned.substring(6);
        } else if (cleaned.startsWith("ftps://")) {
            cleaned = cleaned.substring(7);
        }

        // 如果还有端口号在地址中(如 ftp://192.168.1.150:21),需要分离
        // 但通常FTPClient的connect方法会单独处理端口
        // 这里只移除协议头,端口由另一个参数指定

        return cleaned.trim();
    }


    public FtpUploader(String server, String username, String password) {
        this(server, 21, username, password);
    }

    /**
     * 连接FTP服务器
     * @return 连接是否成功
     * @throws IOException
     */
    public boolean connect() throws IOException {
        ftpClient.connect(server, port);
        int replyCode = ftpClient.getReplyCode();

        if (!FTPReply.isPositiveCompletion(replyCode)) {
            ftpClient.disconnect();
            logger.error("FTP服务器拒绝连接,回复码: {}", replyCode);
            return false;
        }

        boolean loginSuccess = ftpClient.login(username, password);
        if (!loginSuccess) {
            logger.error("FTP登录失败,用户名或密码错误");
            return false;
        }

        // 设置被动模式(适合大多数防火墙)
        ftpClient.enterLocalPassiveMode();

        // 设置文件传输类型为二进制
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        logger.info("成功连接到FTP服务器: {}:{}", server, port);
        return true;
    }

    /**
     * 上传文件
     * @param localFilePath 本地文件路径
     * @param remoteFilePath 远程文件路径
     * @return 上传是否成功
     * @throws IOException
     */
    public boolean uploadFile(String localFilePath, String remoteFilePath) throws IOException {
        File localFile = new File(localFilePath);

        if (!localFile.exists()) {
            logger.error("本地文件不存在: {}", localFilePath);
            return false;
        }

        // 如果远程目录不存在,创建目录
        String remoteDir = getRemoteDirectory(remoteFilePath);
        if (remoteDir != null && !remoteDir.isEmpty()) {
            createRemoteDirectory(remoteDir);
        }

        try (InputStream inputStream = new FileInputStream(localFile)) {
            boolean success = ftpClient.storeFile(remoteFilePath, inputStream);
            if (success) {
                logger.info("文件上传成功: {} -> {}", localFilePath, remoteFilePath);
            } else {
                logger.error("文件上传失败: {}", localFilePath);
            }
            return success;
        }
    }

    /**
     * 上传整个目录
     * @param localDirPath 本地目录路径
     * @param remoteDirPath 远程目录路径
     * @return 上传是否成功
     * @throws IOException
     */
    public boolean uploadDirectory(String localDirPath, String remoteDirPath) throws IOException {
        File localDir = new File(localDirPath);

        if (!localDir.exists() || !localDir.isDirectory()) {
            logger.error("本地目录不存在或不是目录: {}", localDirPath);
            return false;
        }

        // 创建远程目录
        createRemoteDirectory(remoteDirPath);

        File[] files = localDir.listFiles();
        if (files == null) {
            return true;
        }

        boolean allSuccess = true;
        for (File file : files) {
            String remoteFilePath = remoteDirPath + "/" + file.getName();

            if (file.isDirectory()) {
                // 递归上传子目录
                allSuccess &= uploadDirectory(file.getAbsolutePath(), remoteFilePath);
            } else {
                // 上传文件
                allSuccess &= uploadFile(file.getAbsolutePath(), remoteFilePath);
            }
        }

        return allSuccess;
    }

    /**
     * 创建远程目录(支持多级目录创建)
     * @param remoteDirPath 远程目录路径
     * @return 创建是否成功
     * @throws IOException
     */
    private boolean createRemoteDirectory(String remoteDirPath) throws IOException {
        // 分隔符标准化
        remoteDirPath = remoteDirPath.replace("\\", "/");

        String[] directories = remoteDirPath.split("/");
        StringBuilder currentPath = new StringBuilder();

        for (String dir : directories) {
            if (dir.isEmpty()) continue;

            currentPath.append("/").append(dir);
            String path = currentPath.toString();

            // 检查目录是否存在,不存在则创建
            if (!ftpClient.changeWorkingDirectory(path)) {
                boolean success = ftpClient.makeDirectory(path);
                if (success) {
                    logger.debug("创建远程目录: {}", path);
                } else {
                    logger.error("创建远程目录失败: {}", path);
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 从文件路径中提取目录部分
     * @param filePath 文件路径
     * @return 目录路径
     */
    private String getRemoteDirectory(String filePath) {
        int lastSlash = filePath.lastIndexOf('/');
        if (lastSlash > 0) {
            return filePath.substring(0, lastSlash);
        }
        return "";
    }

    /**
     * 断开FTP连接
     */
    public void disconnect() {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
                logger.info("FTP连接已关闭");
            } catch (IOException e) {
                logger.error("关闭FTP连接时出错", e);
            }
        }
    }

    /**
     * 设置连接超时时间(毫秒)
     * @param timeout 超时时间
     */
    public void setTimeout(int timeout) {
        ftpClient.setConnectTimeout(timeout);
        ftpClient.setDefaultTimeout(timeout);
        ftpClient.setDataTimeout(timeout);
    }

    /**
     * 检查FTP服务器是否可连接
     * @return 是否可连接
     */
    public boolean isConnected() {
        return ftpClient.isConnected();
    }
}

App.java

package com.JoinCallCCVoxGuide;


/**
 * Hello world!
 */
public class App {
    protected static final Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        //System.out.println("Hello World!");
 
        // 配置FTP连接参数
        String server = "ftp://192.168.1.150";
        int port =  21;
        String username = "support";
        String password =  "12345678";
        //远程路径
        String remoteFilePath =  "/ysapps/pbxcenter/var/lib/asterisk/sounds/record/NULL.wav";
        //本地文件
        String localFilePath = "d:\\JoinCallCCWav\\";

        localFilePath=localFilePath+"DHCD.wav";

        // 创建上传器实例
        FtpUploader uploader = new FtpUploader(server, port, username, password);

        try {
            // 1. 连接FTP服务器
            if (!uploader.connect()) {
                System.err.println("连接FTP服务器失败");
                return;
            }

            // 2. 设置超时时间(可选)
            uploader.setTimeout(30000);

            // 3. 上传单个文件
            boolean success = uploader.uploadFile(localFilePath, remoteFilePath);
            if (success) {
                System.out.println("文件上传成功");
            }

            // 4. 上传整个目录(可选)
            //String localDir = "/path/to/local/directory";
            //String remoteDir = "/upload/directory";
            //success = uploader.uploadDirectory(localDir, remoteDir);
            //if (success) {
            //    System.out.println("目录上传成功");
            //}

            // 5. 使用FTPS(安全FTP)示例
            //useFtpsExample();

        } catch (Exception e) {
            System.err.println("FTP操作出错: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 确保断开连接
            uploader.disconnect();
        }
    }
 


}