SpringBoot集成FTP实现文件上传下载

SpringBoot集成FTP实现文件上传下载

安装vsftpd

阿里云CentOS7.6手动安装ftp

开始集成ftp

1.首先引入jar包

我用的是gradle 换成maven的话还是同样的包,换成对应的maven里面的写法就行了


dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation group: 'commons-net', name: 'commons-net', version: '3.8.0'
    compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
    compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.20'
    implementation group: 'io.netty', name: 'netty-common', version: '4.1.68.Final'

}

2.创建工具类


package com.dnydys.util;

import io.netty.util.CharsetUtil;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

/**
 * @Classname FtpUtil
 * @Description TODO
 * @Date 2021/12/17 19:52
 * @Created by hasee
 */
public class FtpUtil {

    public FTPClient ftpClient = new FTPClient();
    //ftp服务器地址
    public static final String HOSTNAME = "101.133.226.94";
    //ftp服务器端口号
    public static final int PORT = 21;
    //登录ftp服务器的用户名和密码
    public static final String USERNAME = "ftptest";
    public static final String PWD = "1a2s3d4f";
    //ftpuser的基础目录
    //所有用户的文件都是在这个目录下
//    public static final String BASEPATH = "/var/ftp/test";

    //本地字符编码
    static String LOCAL_CHARSET = "UTF-8";
    // FTP协议里面,规定文件名编码为iso-8859-1
    static String SERVER_CHARSET = "ISO-8859-1";


    /**
     * @className FtpUtil
     * @author dnydys
     * @description 用于登录ftp服务器
     * @updateTime 2021/12/17 20:14
     * @return: void
     * @version 1.0
     */
    public Boolean ftpLogin() throws IOException {

        ftpClient.setAutodetectUTF8(true);
        ftpClient.setCharset(CharsetUtil.UTF_8);
        ftpClient.setControlEncoding(CharsetUtil.UTF_8.name());
        //服务器地址和端口
        ftpClient.connect(HOSTNAME,PORT);

        //登录的用户名和密码
        Boolean isLogin = ftpClient.login(USERNAME, PWD);
        return isLogin;
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 用于退出ftp服务器
     * @updateTime 2021/12/17 20:15
     * @return: void
     * @version 1.0
     */
    public Boolean ftpLogout() throws IOException {
        Boolean isLogout = ftpClient.logout();
        return isLogout;
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 切换目录至基础目录
     * @updateTime 2021/12/17 21:53
     * @return: java.lang.Boolean
     * @version 1.0
     */
    public Boolean changeWorkingDirectory() throws IOException {
        String BASEPATH = "/var/ftp/0000";
        boolean b = ftpClient.changeWorkingDirectory(BASEPATH);
        return b;
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 切换目录至用户目录
     * @updateTime 2021/12/17 21:54
     * @return: java.lang.Boolean
     * @version 1.0
     */
    public Boolean changeWorkingDirectory(String userPath) throws IOException {
        boolean b = ftpClient.changeWorkingDirectory(userPath);
        return b ;
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 创建用户目录 false说明用户目录已经存在
     * @updateTime 2021/12/17 21:59
     * @return: java.lang.Boolean
     * @version 1.0
     */
    public Boolean makeDirectory(String userid) throws IOException {
        boolean b = ftpClient.makeDirectory(userid);
        return b;
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 设置文件类型 二进制形式传文件
     * @updateTime 2021/12/17 22:07
     * @return: java.lang.Boolean
     * @version 1.0
     */
    public Boolean setFileType() throws IOException {
        return ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 1.服务器端保存的文件名,2.上传文件的inputstream
     * @updateTime 2021/12/17 22:24
     * @return: java.lang.Boolean
     * @version 1.0
     */
    public Boolean storeFile(String filename, FileInputStream inputStream) throws IOException {
//         开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
//        if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
//            LOCAL_CHARSET = "UTF-8";
//        }
//        ftpClient.setControlEncoding(LOCAL_CHARSET);
//        return ftpClient.storeFile(new String(filename.getBytes(LOCAL_CHARSET),
//            SERVER_CHARSET),inputStream);

        return ftpClient.storeFile(filename,inputStream);
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 打印用户当前所在目录
     * @updateTime 2021/12/18 9:59
     * @return: java.lang.String
     * @version 1.0
     */
    public String printWorkingDirectory() throws IOException {
        return ftpClient.printWorkingDirectory();
    }
    /**
     * @className FtpUtil
     * @author dnydys
     * @description
     * @updateTime 2021/12/18 10:20 
     * @return: void

     * @version 1.0
     */
    public void enterLocalPassiveMode(){
//        每次数据连接之前ftp client告诉ftp server开通 一个端口来传输数据。
//        原因是ftp每次开启不同的端口传输数据,linux上,安全限制,某些端口没有开启,出现阻塞
//        但是不理解他说的被动和主动方式的含义。
//        今天回来查资料知道:
//        FTP协议有两种工作方式,Port和Pasv方式,主动和被动式。
//        (1) PORT(主动模式)
//        工作的原理: FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,客户端随机开放一个端口(1024以上),发送 PORT命令到FTP服务器,告诉服务器客户端采用主动模式并开放端口;FTP服务器收到PORT主动模式命令和端口号后,通过服务器的20端口和客户端开放的端口连接,发送数据
//            (2) PASV(被动模式) 这就是上面方法的作用。
//        工作的原理:FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,发送PASV命令到FTP服务器, 服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端, 客户端再连接到服务器开放的端口进行数据传输
        ftpClient.enterLocalPassiveMode();
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description 查询所有文件列表
     * @updateTime 2021/12/18 22:05
     * @return: void
     * @version 1.0
     */
    public FTPFile[] listFiles() throws IOException {
        if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
            LOCAL_CHARSET = "UTF-8";
        }
        ftpClient.setControlEncoding(LOCAL_CHARSET);
        return ftpClient.listFiles();
    }
    
    /**
     * @className FtpUtil
     * @author dnydys
     * @description 检索文件
     * @updateTime 2021/12/18 22:12 
     * @return: java.lang.Boolean
     * @version 1.0
     */
    public Boolean retrieveFile(String fileName, FileOutputStream outputStream) throws IOException {
        return ftpClient.retrieveFile(fileName, outputStream);
    }

    /**
     * @className FtpUtil
     * @author dnydys
     * @description
     * @updateTime 2021/12/18 23:07
     * @return: null
     * @version 1.0
     */
    public InputStream retrieveFileStream(String fileName) throws IOException {
        return ftpClient.retrieveFileStream(fileName);
    }


}


3.创建ServiceImpl

service我就不放了


package com.dnydys.service.impl;

import com.dnydys.common.baseRespone.ResultInfo;
import com.dnydys.common.code.ResponseCode;
import com.dnydys.service.FileUploadService;
import com.dnydys.util.FtpUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.stereotype.Service;

/**
 * @Classname FileUploadServiceImpl
 * @Description TODO
 * @Date 2021/12/17 20:26
 * @Created by hasee
 */
@Service
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {


    @Override
    public ResultInfo fileUpload(String localPath,String userid,String fileName) throws IOException {
        ResultInfo resultInfo = new ResultInfo();
        FtpUtil ftpUtil = new FtpUtil();
        Boolean aBoolean = ftpUtil.ftpLogin();
        if (!aBoolean){
            log.error("FTP用户登录失败");
            resultInfo.setResultCode(ResponseCode.FTP_LOGIN_ERROR);
            return resultInfo;
        }

//        localPath = new String(localPath.getBytes("GBK"),"UTF-8");
//        fileName = new String(fileName.getBytes("GBK"),"UTF-8");
        FileInputStream inputStream = new FileInputStream(new File(localPath));
        //ftptest用户登陆上去之后默认是在BasePath之下,所以不用切换,后续不是BasePath的话再放开就行了
//        Boolean isChangeBaseSuccess= ftpUtil.changeWorkingDirectory();
//        if (!isChangeBaseSuccess){
//            log.error("FTP切换基础目录失败");
//            resultInfo.setResultCode(ResponseCode.FTP_CHANGE_BASEPATH_ERROR);
//            return resultInfo;
//        }

        Boolean isChangeUserSuccess = ftpUtil.changeWorkingDirectory(userid);
        if (!isChangeUserSuccess){
            log.error("FTP切换用户目录失败,该用户目录不存在,先创建用户目录");
            Boolean isMakeDirectory = ftpUtil.makeDirectory(userid);
            if (!isMakeDirectory){
                log.error(userid+"用户目录创建失败");
                resultInfo.setResultCode(ResponseCode.FTP_LOGIN_ERROR);
                return resultInfo;
            }
        }
        Boolean isStoreFile = ftpUtil.storeFile(fileName, inputStream);
        if(!isStoreFile){
            log.error("FTP服务器端上传文件失败");
            resultInfo.setResultCode(ResponseCode.FTP_STOREFILE_ERROR);
            return resultInfo;
        }
        Boolean isLogout = ftpUtil.ftpLogout();
        if (!isLogout){
            log.error("FTP服务器登出失败");
            resultInfo.setResultCode(ResponseCode.FTP_LOGOUT_ERROR);
            return resultInfo;
        }
        resultInfo.setResultCode(ResponseCode.SUCCESS);
        return resultInfo;
    }

    @SneakyThrows
    @Override
    public ResultInfo fileDownload(String localPath,String userid,String fileName) {
        ResultInfo resultInfo = new ResultInfo();
        FtpUtil ftpUtil = new FtpUtil();
        Boolean isLogin = ftpUtil.ftpLogin();
        if (!isLogin){
            log.error("FTP用户登录失败");
            resultInfo.setResultCode(ResponseCode.FTP_LOGIN_ERROR);
            return resultInfo;
        }

        Boolean isChangeUserSuccess = ftpUtil.changeWorkingDirectory(userid);
        if (!isChangeUserSuccess){
            log.error("FTP切换用户目录失败");
            log.error("FTP切换用户目录失败,该用户目录不存在,先创建用户目录");
            Boolean isMakeDirectory = ftpUtil.makeDirectory(userid);
            if (!isMakeDirectory){
                log.error(userid+"用户目录创建失败");
                resultInfo.setResultCode(ResponseCode.FTP_LOGIN_ERROR);
                return resultInfo;
            }
        }
        //每次数据连接之前ftp client告诉ftp server开通 一个端口来传输数据。
        ftpUtil.enterLocalPassiveMode();
        //打印当前目录
//        String s = ftpUtil.printWorkingDirectory();
        FTPFile[] ftpFiles = ftpUtil.listFiles();
        boolean b = false;
//        fileName = new String(fileName.getBytes("GBK"),"iso-8859-1");
        if (ftpFiles.length > 0){
            for (FTPFile ff : ftpFiles) {
                if (ff.getName().equals(fileName)) {
                    ftpUtil.enterLocalPassiveMode();
                    FileOutputStream outputStream = new FileOutputStream(new File(localPath+"\\"+fileName));
                    b = ftpUtil.retrieveFile(fileName, outputStream);
                    outputStream.close();
                }
            }
        }
        if (!b){
            log.error("未查找到相关文件");
            resultInfo.setResultCode(ResponseCode.FTP_RETRIEVEFILE_ERROR);
            resultInfo.setData(b);
            return resultInfo;
        }
        Boolean isLogout = ftpUtil.ftpLogout();
        if (!isLogout){
            log.error("FTP用户登出失败");
            resultInfo.setResultCode(ResponseCode.FTP_LOGOUT_ERROR);
            return resultInfo;
        }
        resultInfo.setResultCode(ResponseCode.SUCCESS);
        resultInfo.setData(b);
        return resultInfo;
    }
}


4.创建测试类


package com.dnydys.service;

import com.dnydys.common.baseRespone.ResultInfo;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @Classname FileUploadServiceTest
 * @Description TODO
 * @Date 2021/12/17 23:28
 * @Created by hasee
 */
@SpringBootTest
public class FileUploadServiceTest {

    @Autowired
    private FileUploadService fileUploadService;

    //文件上传
    @Test
    public void fileUpload() throws IOException {

        String localPath = "C:\\Users\\hasee\\Desktop\\DNYDIS\\testfile.txt";
        System.out.println("+++++++++++++++++++++"+localPath);

        String fileName = "testfile.txt";
        String userid = "22";
        ResultInfo resultInfo = fileUploadService.fileUpload(localPath, userid, fileName);
        System.out.println(resultInfo.getResultCode());
    }

    //文件下载
    @Test
    public void fileDownload() throws IOException {

        String localPath = "C:\\Users\\hasee\\Desktop\\download";
        System.out.println("+++++++++++++++++++++"+localPath);
        String fileName = "testfile.txt";

        String userid = "22";
        ResultInfo resultInfo = fileUploadService.fileDownload(localPath, userid, fileName);
        System.out.println(resultInfo.getResultCode());
    }
}


基本完工 看效果

上传

在这里插入图片描述

下载

在这里插入图片描述

文件内容

为了解决这个文件内容乱码可废了老大劲儿了
搞得我感觉喝一杯黑芝麻糊泡枸杞压压惊
在这里插入图片描述

代码下载

最后附上代码链接地址
https://github.com/DNYDYS/springboot-FTP.git

有什么问题随时可以留言或者私信
赶紧接着喝我的黑芝麻糊泡枸杞去

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值