Java实现ftp上传下载功能

前言

平时开发系统的时候,如果需要上传文档,一般都是通过开发好的基础组件比如网盘来上传保存文件。下载的话,一般也是通过http的方式去下载文件。但是遇到比较大的文件,或者遇到了其他的业务需求,有时候还是需要用到ftp协议去传输文件。毕竟ftp作为专业的传输文件协议,还是有着传输效率高的优点的。

搞一个ftp工具类

上传下载还是应该写一个工具类来实现比较方便。这里我们需要引入一个commons-net-3.6.jar的jar包。可以上Apache的官网下载,也可以从文末我分享的网盘链接下载。

一言不合就上代码吧

整个ftp工具类的代码先贴在这里,其中主要代码都有注释。注释会告诉你每一行代码都是做什么的。

package utils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.SocketException;

/**
 * Created by tinybye on 2017/10/23.
 */
public class FtpClientUtils {
    private static Logger logger = Logger.getLogger(FtpClientUtils.class);
    /**
     * 获取FTPClient对象
     * @param ftpHost
     *            FTP主机服务器
     * @param ftpPassword
     *            FTP 登录密码
     * @param ftpUserName
     *            FTP登录用户名
     * @param ftpPort
     *            FTP端口 默认为21
     * @return
     */
    public static FTPClient getFTPClient(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort) {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = new FTPClient();
            // 连接FTP服务器
            ftpClient.connect(ftpHost, ftpPort);
            // 登陆FTP服务器
            ftpClient.login(ftpUserName, ftpPassword);
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                logger.info("未连接到FTP,用户名或密码错误。");
                ftpClient.disconnect();
            } else {
                logger.info("FTP连接成功。");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            logger.info("FTP的IP地址可能错误,请正确配置。");
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("FTP的端口错误,请正确配置。");
        }
        return ftpClient;
    }

    /**
     * 从FTP服务器下载文件 demo
     * @param ftpHost FTP IP地址
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP用户名密码
     * @param ftpPort FTP端口
     * @param ftpPath FTP服务器中文件所在路径 格式: ftptest/document
     * @param localPath 下载到本地的位置 格式:windows:E:/download linux或mac:/Users/tinybye/Downloads
     * @param fileName 文件名称
     */
    public static void downloadFtpFile(String ftpHost, String ftpUserName,
                                       String ftpPassword, int ftpPort, String ftpPath, String localPath,
                                       String fileName) {

        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
            // 设置服务器的编码格式,如果与服务器不一致则会导致中文文件下载失败
            ftpClient.setControlEncoding("GBK");
            //设置文件类型 为二进制
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //数据连接之前开通端口传输数据
            ftpClient.enterLocalPassiveMode();
            //切换工作路径
            ftpClient.changeWorkingDirectory(ftpPath);
            // 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
            // 如果不想下载文件,比如直接处理文件流做转存操作,则可以获取文件流,不需要在本地服务器生成文件占用存储空间。但是在使用完文件流后需要关闭并调用completePendingCommand()方法
            InputStream fileInputStream = ftpClient.retrieveFileStream((new String(fileName.getBytes("GBK"), "ISO-8859-1")));

            //处理文件流start
            // 关闭文件流,调用completePendingCommand,否则会导致之后的ftpClient无法继续使用
            fileInputStream.close();
            ftpClient.completePendingCommand();
            //处理文件流end

            // 保存到本地start
            File localFile = new File( localPath + File.separatorChar + fileName);
            OutputStream os = new FileOutputStream(localFile);
            // 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
            ftpClient.retrieveFile(new String(fileName.getBytes("GBK"), "ISO-8859-1"), os);
            os.close();
            // 保存到本地end
            ftpClient.logout();

        } catch (FileNotFoundException e) {
            logger.error("没有找到" + ftpPath + "文件");
            e.printStackTrace();
        } catch (SocketException e) {
            logger.error("连接FTP失败.");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("文件读取错误。");
            e.printStackTrace();
        }
    }
    /**
     * 上传文件到FTP服务器 demo
     * @param ftpHost FTP IP地址
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP用户名密码
     * @param ftpPort FTP端口
     * @param ftpPath FTP服务器中文件所在路径 格式: ftptest/document
     * @param localPath 本地文件的位置 格式:windows:E:/download linux或mac:/Users/tinybye/Downloads
     * @param fileName 文件名称
     */
    public static void uploadFtpFile(String ftpHost, String ftpUserName,
                                       String ftpPassword, int ftpPort, String ftpPath, String localPath,
                                       String fileName) {

        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
            // 设置服务器的编码格式,如果与服务器不一致则会导致中文文件下载失败
            ftpClient.setControlEncoding("GBK");
            //设置文件类型 为二进制
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //数据连接之前开通端口传输数据
            ftpClient.enterLocalPassiveMode();
            //切换工作路径
            ftpClient.changeWorkingDirectory(ftpPath);
            // 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
            // 上传文件start
            File localFile = new File( localPath + File.separatorChar + fileName);
            FileInputStream fileInputStream = new FileInputStream(localFile);
            // 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
            ftpClient.storeFile(new String(fileName.getBytes("GBK"), "ISO-8859-1"), fileInputStream);
            fileInputStream.close();
            // 上传文件end
            ftpClient.logout();

        } catch (FileNotFoundException e) {
            logger.error("没有找到" + localPath + "文件");
            e.printStackTrace();
        } catch (SocketException e) {
            logger.error("连接FTP失败.");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("文件读取错误。");
            e.printStackTrace();
        }
    }
}

常见问题与注意事项

因为在边查资料边开发的过程中还是遇到了一些问题,感觉都是应该注意的问题。其实注释里都有说,但是在这里总结一下吧。

文件名为中文的问题

因为ftp协议中文件名需要ISO-8859-1编码,所以上传和下载的时候要注意对文件名进行转码。当然,这里要注意的是,你要确定ftp服务器设置的编码是utf-8还是GBK,并使用

ftpClient.setControlEncoding("GBK");

进行设置,然后在后面进行转码。

下载文件流后的操作

在使用

ftpClient.retrieveFileStream();

方法从ftp服务器上获取文件流之后,需要先关闭文件流,然后调用

ftpClient.completePendingCommand();

方法。否则之后的ftpClient操作将会失败。

其他

commons-net-3.6.jar包下载

commons-net-3.6.jar

参考文章

Java代码实现FTP文件下载
使用FPT上传下载文件和解决中文名文件乱码问题
调用FTPClient 的retrieveFileStream(String remote)方法后的处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白码上飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值