# Java Ftp 文件上传下载

Posted MarlonBrando1998

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# Java Ftp 文件上传下载相关的知识,希望对你有一定的参考价值。

环境准备
  • Win10 搭建 ftp
Ftp 端口
  • 21端口:命令端口
  • 20端口:FTP传输数据端口,是否会用到20端口与FTP传输模式有关,主动模式使用20端口传输,被动模式下服务器端和客户端协商决定端口。
Ftp 主动模式、被动模式

​ Ftp支持两种方式的传输:文本(ASCII)方式和二进制(Binary)方式,通常文本文件的传输采用ASCII方式,图像、声音文件等非文本文件采用二进制方式传输。

  • 主动模式:客户端向Ftp服务器端发送端口信息,由服务器主动连接该端口。

  • 被动模式:FTP服务器开启并发送端口信息给客户端,由客户端连接该端口,服务器被动接受连接。

添加依赖
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.3</version>
</dependency>
FtpUtils
/**
 * @author lidong
 */
public class FtpUtils {

    private static final Logger logger = LoggerFactory.getLogger(FtpUtils.class);

    /**
     * @param ftpUrl      ftp 主机地址
     * @param ftpUserName 用户名
     * @param ftpPassword 密码
     * @param port        端口号
     * @return
     */
    public static FTPClient getFtpClient(String ftpUrl, String ftpUserName, String ftpPassword, int port) {
        FTPClient ftpClient = new FTPClient();
        try {
            // 获取连接
            ftpClient.connect(ftpUrl, port);
            // 登录
            ftpClient.login(ftpUserName, ftpPassword);
            int reply;
            reply = ftpClient.getReplyCode();
            if (FTPReply.isPositiveCompletion(reply)) {
                logger.info("成功登录 ftp 服务器...");
                logger.info("成功登录服务器,被动模式主机:[{}:{}]", ftpClient.getPassiveHost(), ftpClient.getPassivePort());
                logger.info("成功登录服务器,主动模式主机:[{}:{}]", ftpClient.getRemoteAddress(), ftpClient.getRemotePort());
                logger.info("成功登录服务器,本地主机:[{}:{}]", ftpClient.getLocalAddress(), ftpClient.getLocalPort());
                logger.info("成功登录服务器,返回代码:[{}], 显示状态[{}]", ftpClient.getReplyCode(), ftpClient.getStatus());
            } else {
                ftpClient.disconnect();
                logger.info("Ftp 登录之后的 ReplyCode{}:", ftpClient.getReplyCode());
            }
            // 解决创建的文件含有汉字乱码问题
            ftpClient.setControlEncoding("UTF-8");
            // 设置成以二进制传输
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return ftpClient;
    }

    /**
     * 获得 Ftp 上文件的流
     *
     * @param ftpClient        ftp 连接对象
     * @param ftpPathDirectory ftp 上文件目录
     * @param fileName         文件名称
     * @return
     * @throws IOException
     */
    public static InputStream getFtpInputStream(FTPClient ftpClient, String ftpPathDirectory, String fileName) throws IOException {
        InputStream inputStream = null;
        boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(ftpPathDirectory);
        if (!changeWorkingDirectory) {
            throw new IllegalArgumentException("当前文件夹不存在!");
        }
        /**
         * 主动模式传送数据时是“服务器”连接到“客户端”的端口;被动模式传送数据是“客户端”连接到“服务器”的端口
         * 主动模式需要客户端必须开放端口给服务器,很多客户端都是在防火墙内,开放端口给FTP服务器访问比较困难。
         * 被动模式只需要服务器端开放端口给客户端连接就行了。
         */
        // 被动模式
        ftpClient.enterLocalPassiveMode();
        try {
            inputStream = ftpClient.retrieveFileStream(new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
        } catch (Exception e) {
            logger.error("Error Occur{}:", e.getMessage());
        }
        if (inputStream == null) {
            // 主动模式
            ftpClient.enterLocalActiveMode();
            inputStream = ftpClient.retrieveFileStream(new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
        }
        Objects.requireNonNull(inputStream);
        return inputStream;
    }

    /**
     * 下载 ftp 文件
     *
     * @param ftpClient
     * @param pathDirectory ftp 文件目录
     * @param fileName      ftp 文件名称
     * @param downLoadPath  下载路径
     * @return
     * @throws IOException
     */
    public static String downLoadFtpFile(FTPClient ftpClient, String pathDirectory, String fileName, String downLoadPath) throws IOException {
        boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(pathDirectory);
        if (!changeWorkingDirectory) {
            throw new IllegalArgumentException("当前文件目录不存在!");
        }
        // 文件绝对路径
        String fileFullPath = downLoadPath + fileName;
        File file = new File(fileFullPath);
        OutputStream outputStream = new FileOutputStream(file);
        for (FTPFile ftpFile : ftpClient.listFiles()) {
            String ftpFileName = ftpFile.getName();
            logger.info("目录:{} 下有文件:{}", pathDirectory, ftpFileName);
            if (ftpFileName.contains(fileName)) {
                ftpClient.retrieveFile(ftpFileName, outputStream);
                outputStream.close();
            }
        }
        return "下载成功,下载的文件路径为:" + fileFullPath;
    }

    /**
     * 文件上传
     *
     * @param ftpClient
     * @param ftpUploadPath 文件上传 ftp 目录
     * @param fileFullPath  本地文件 绝对路径
     * @return
     * @throws IOException
     */
    public static String uploadFtpFile(FTPClient ftpClient, String ftpUploadPath, String fileFullPath) throws IOException {
        boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(ftpUploadPath);
        if (!changeWorkingDirectory) {
            ftpClient.makeDirectory(ftpUploadPath);
            logger.info("在 ftp 下创建文件夹:{}", ftpUploadPath);
        }
        ftpClient.changeWorkingDirectory(ftpUploadPath);
        File file = new File(fileFullPath);
        InputStream inputStream = new FileInputStream(file);
        ftpClient.storeFile(file.getName(), inputStream);
        return "上传成功,上传的文件路径为:" + ftpUploadPath + file.getName();
    }


    /**
     * 列出指定目录下的文件
     *
     * @param ftpClient
     * @param filePathDirectory
     * @return
     */
    public static FTPFile[] listFtpFiles(FTPClient ftpClient, String filePathDirectory) throws IOException {
        boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(filePathDirectory);
        if (!changeWorkingDirectory) {
            throw new IllegalArgumentException("当前目录不存在!");
        }
        return ftpClient.listFiles();
    }


    private FTPClient getFtpClient() {
        String url = "100.100.100.100";
        int port = 21;
        String username = "admin";
        String password = "199917LD";
        return getFtpClient(url, username, password, port);
    }

    @Test
    public void testDownLoad() {
        try {
            String message = downLoadFtpFile(getFtpClient(), "/20210704/", "test_metadata20210701012856.xml", "D:\\\\迅雷云盘\\\\");
            logger.info(message);
        } catch (IOException e) {
            logger.error("Error Occur:{}", e.getMessage());
        }
    }

    @Test
    public void testUpLoad() {
        try {
            String message = uploadFtpFile(getFtpClient(), "/test/", "C:\\\\windows-version.txt");
            logger.info(message);
        } catch (IOException e) {
            logger.error("Error Occur:{}", e.getMessage());
        }
    }

    @Test
    public void testListFiles() {
        try {
            FTPFile[] ftpFiles = listFtpFiles(getFtpClient(), "/test");
            for (FTPFile ftpFile : ftpFiles) {
                logger.info(ftpFile.getName());
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

}

以上是关于# Java Ftp 文件上传下载的主要内容,如果未能解决你的问题,请参考以下文章

Java上传文件FTP服务器代码

java在浏览器上获取FTP读文件路径

我的代码库-Java8实现FTP与SFTP文件上传下载

Java代码实现FTP单个文件下载

Java ftp 上传文件和下载文件

java程序在linux系统下运行上传文件到ftp服务器出错代码 “451 参数错误”