栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java实现FTP文件上传和下载

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java实现FTP文件上传和下载

目录
    • 一、背景
    • 二、maven依赖
    • 三、FTP工具类
      • 3.1、主动模式(PORT)
      • 3.2、被动模式(PASV)
    • 四、验证
      • 4.1、dos下操作FTP
      • 4.2、FTP文件上传
      • 4.3、FTP文件下载

一、背景

  我在之前的文章(Java实现文件上传和下载)里讲过非FTP文件的上传和下载,今天我们来讲一下FTP文件上传和下载,本文测试过程中Spring Boot 版本为2.5.2commons-net 版本为3.8.0,JDK环境为 1.8。本文是在window环境下完成的,因为本机环境的复杂性,是把本机的防火墙关闭了的(不然dos登录后操作不了,或者上传下载超时)。

二、maven依赖

pom.xml



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.2
         
    
    
    com.alian
    ftp
    0.0.1-SNAPSHOT
    ftp
    java实现FTP文件上传下载

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.apache.commons
            commons-lang3
            3.12.0
        

        
            commons-net
            commons-net
            3.8.0
        

        
            org.projectlombok
            lombok
            1.16.14
        

        
            junit
            junit
            4.12
            compile
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


三、FTP工具类

  本工具类中包含四个方法,实例化方法,上传文件,下载文件,及关闭连接方法。

ApacheFtpClient.java

package com.alian.ftp.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

import java.io.*;

@Slf4j
public class ApacheFtpClient {

    private FTPClient ftpClient;

    
    public ApacheFtpClient(String hostName, int port, String userName, String password) throws IOException {
        ftpClient = new FTPClient();
        //设置传输命令的超时
        ftpClient.setDefaultTimeout(20000);//毫秒
        //设置两个服务连接超时时间
        ftpClient.setConnectTimeout(10000);//毫秒
        //被动模式下设置数据传输的超时时间
        ftpClient.setDataTimeout(15000);//毫秒
        //被动模式(需要设置在连接之前)
        ftpClient.enterLocalPassiveMode();
        //连接FTP
        ftpClient.connect(hostName, port);
        //更加账户密码登录服务
        ftpClient.login(userName, password);
    }

    
    public Pair uploadFile(String remoteUploadDirectory, String localUploadFilePathName, String encoding) {
        FileInputStream fis = null;
        try {
            // 如果不能进入dir下,说明此目录不存在!
            if (!ftpClient.changeWorkingDirectory(remoteUploadDirectory)) {
                log.info("没有目录:{}", remoteUploadDirectory);
                if (!ftpClient.makeDirectory(remoteUploadDirectory)) {
                    log.info("创建文件目录【{}】 失败!", remoteUploadDirectory);
                    return Pair.of(false, "创建文件目录【" + remoteUploadDirectory + "】 失败");
                }
            }
            //进入文件目录
            ftpClient.changeWorkingDirectory(remoteUploadDirectory);
            //创建文件流
            fis = new FileInputStream(new File(localUploadFilePathName));
            //设置上传目录
            ftpClient.setBufferSize(1024);
            //设置编码(默认是ISO-8859-1)
            ftpClient.setControlEncoding(encoding);
            //设置文件类型(二进制)
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //FTP服务器上最终的名字
            String uploadFileName = localUploadFilePathName.substring(localUploadFilePathName.lastIndexOf(File.separator) + 1);
            //文件上传
            boolean b = ftpClient.storeFile(uploadFileName, fis);
            int replyCode = ftpClient.getReplyCode();
            log.info("上传文件响应码:{}", replyCode);
            return Pair.of(b, b ? "上传成功" : "上传失败");
        } catch (Exception e) {
            log.error("FTP上传文件异常!:", e);
            return Pair.of(false, "上传文件异常");
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                log.error("关闭流发生异常!", e);
            }
        }
    }

    
    public Pair downloadFile(String remoteDownloadDirectory, String localDirectory, String downloadFileName) {
        OutputStream out = null;
        try {
            if (StringUtils.isBlank(downloadFileName)) {
                return Pair.of(false, "要下载的文件不能为空");
            }
            //工作目录切换到下载文件的目录下
            if (!ftpClient.changeWorkingDirectory(remoteDownloadDirectory)) {
                log.info("目录不存在:{}", remoteDownloadDirectory);
                return Pair.of(false, "目录不存在");
            }
            //获取目录下所有文件
            FTPFile[] files = ftpClient.listFiles();
            if (files.length < 1) {
                return Pair.of(false, "目录为空");
            }
            boolean fileExist = false;
            boolean downloadFlag = false;
            //遍历文件列表
            for (FTPFile ftpFile : files) {
                String localFile = localDirectory + File.separator + downloadFileName;
                //是否存在要下载的文件
                if (downloadFileName.equals(ftpFile.getName())) {
                    fileExist = true;
                    out = new FileOutputStream(localFile);
                    //下载
                    downloadFlag = ftpClient.retrieveFile(downloadFileName, out);
                    int replyCode = ftpClient.getReplyCode();
                    log.info("下载文件响应码:{}", replyCode);
                    break;
                }
            }
            if (!fileExist) {
                return Pair.of(false, "FTP服务器上文件不存在");
            }
            return Pair.of(downloadFlag, downloadFlag ? "下载成功" : "下载失败");
        } catch (Exception e) {
            log.error("FTP下载文件异常!:", e);
            return Pair.of(false, "下载文件异常");
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void close() {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

  注意构造方法中的调用,FTP协议有两种工作方式:

	//被动模式(需要设置在连接之前)
    ftpClient.enterLocalPassiveMode();
3.1、主动模式(PORT)

  主动模式的FTP是指服务器主动连接客户端的数据端口。

  • FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,同时开放N+1号端口进行监听,然后发送PORT命令到FTP服务器,告知是主动模式
  • FTP服务器给客户端的命令端口返回一个ACK的应答码
  • FTP客户端发出数据传输的指令
  • FTP服务器发起一个从它自己的数据端口(一般是20端口)到客户端先前指定的数据端口(N+1)的连接
  • FTP客户端返回一个ACK后,进行数据传输
3.2、被动模式(PASV)

  被动模式的FTP是指服务器被动地等待客户端连接自己的数据端口。

  • FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,同时会开启N+1号端口。然后向服务器发送PASV命令,告知是被动模式
  • FTP服务器收到命令后,会开放一个大于1024的端口P进行监听,然后用PORT命令通知客户端,服务端的数据端口是P
  • FTP客户端发出数据传输的指令,会通过N+1号数据端口连接服务器的端口P
  • FTP服务器给客户端的数据端口返回一个ACK的应答码,然后在两个端口之间进行数据传输
四、验证 4.1、dos下操作FTP

  如果你是window环境下操作FTP,建议关闭防火墙操作。
输入命令:

#在cmd命令提示符下输入(ftp加FTP服务器地址)
ftp 192.168.0.151
#根据提示输入用户名
Alian
#根据提示输入登录密码
Alian@1223

本文登录后的文件列表:

4.2、FTP文件上传
    @Test
    public void upload() throws IOException {
        ApacheFtpClient apacheFtpClient = new ApacheFtpClient("192.168.0.151", 21, "Alian", "Alian@1223");
        Pair pair = apacheFtpClient.uploadFile("apacheFTP", "C:\myFile\CSDN\result.png", "GBK");
        log.info("上传返回结果:{}", pair);
        apacheFtpClient.close();
    }

运行结果:

17:16:55.830 [main] INFO com.alian.ftp.utils.ApacheFtpClient - 上传文件响应码:226
17:16:55.835 [main] INFO com.alian.ftp.service.TestApacheFtpService - 上传返回结果:(true,上传成功)

登录FTP服务器上查看文件如下:

4.3、FTP文件下载
    @Test
    public void download() throws IOException {
        ApacheFtpClient apacheFtpClient = new ApacheFtpClient("192.168.0.151", 21, "Alian", "Alian@1223");
        Pair pair = apacheFtpClient.downloadFile("apacheFTP", "C:\myFile\download", "result.png");
        log.info("下载返回结果:{}", pair);
        apacheFtpClient.close();
    }

运行结果:

17:20:37.126 [main] INFO com.alian.ftp.utils.ApacheFtpClient - 下载文件响应码:226
17:20:37.130 [main] INFO com.alian.ftp.service.TestApacheFtpService - 下载返回结果:(true,下载成功)

进入到我们本地下载的目录,结果如下:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/601281.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号