spring-boot整合FTP文件服务器

@TOC

一,扫盲篇:什么是FTP?

  • FTP 服务器是支持 FTP协议的服务器。在电脑中安装FTP工具将电脑中的数据传输到服 务器当中,这时服务器就称为FTP服务器,而我们的电脑称为客户端。对于FTP服务器, 用户可通过FTP软件和服务器建立连接,进行文件上传、删除、修改权限等操作。
    FTP 服务器一般分为两类:①Windows FTP服务器 ②Linux FTP 服务器。

二,SpringBoot 集成 FTP文件服务器

1.要在springboot中集成FTP,首先要引入对应的Maven依赖。
<!--ftp文件上传-->
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.3</version>
</dependency>
2.spring-boot 配置文件application.中配置 FTP
#注意使用自己的IP和配置
#ftp use
ftp.server=39.97.98.252
ftp.port=65501
ftp.userName=hopsonftp
ftp.userPassword=hopsonSGgs12344321
ftp.bastPath=/hopson
ftp.imageBaseUrl=http://39.97.98.252:11018/hopson/image/
ftp.removeUrl=/hopson/image
3.编写 FTP文件服务器 工具类。下面是完成代码,复制即用

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.MalformedURLException;

/**
 * ftp工具类
 * 2020年8月5日11:53:20
 * author : skj
 */
@Slf4j
@Component
@Configuration
public class FtpUtil {

   //ftp服务器地址
    @Value("${upload.host}")
    private String hostname;

    //ftp服务器端口
    @Value("${upload.port}")
    private int port;

    //ftp登录账号
    @Value("${upload.username}")
    private String username;

    //ftp登录密码
    @Value("${upload.password}")
    private String password;

    //ftp保存目录
    @Value("${upload.bastPath}")
    private String basePath;


    /**
     * 初始化ftp服务器
     */
    public FTPClient getFtpClient() {
        FTPClient ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");

        try {
            ftpClient.setDataTimeout(1000 * 120);//设置连接超时时间


            log.info("connecting...ftp服务器:" + hostname + ":" + hostname);
            log.info("connecting...ftp服务器:" + port + ":" + port);
            log.info("connecting...ftp服务器:" + username + ":" + username);
            log.info("connecting...ftp服务器:" + password + ":" + password);
            ftpClient.connect(hostname,port); // 连接ftp服务器
            ftpClient.login(username, password); // 登录ftp服务器
            int replyCode = ftpClient.getReplyCode(); // 是否成功登录服务器
            if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
                    "OPTS UTF8", "ON"))) {      // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                LOCAL_CHARSET = "UTF-8";
            }
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                System.out.println("connect failed...ftp服务器:" + hostname + ":" + port);
            }
            System.out.println("connect successfu...ftp服务器:" + hostname + ":" + port);
        } catch (MalformedURLException e) {
            logger.error(e.getMessage(), e);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return ftpClient;
    }


    /**
     * 上传文件
     *
     * @param targetDir    ftp服务保存地址
     * @param fileName    上传到ftp的文件名
     * @param inputStream 输入文件流
     * @return
     */
    public boolean uploadFileToFtp(String targetDir, String fileName, InputStream inputStream) {
        boolean isSuccess = false;
        String servicePath = String.format("%s%s%s", basePath, "/", targetDir,"/");
        FTPClient ftpClient = getFtpClient();
        try {
            if (ftpClient.isConnected()) {
                log.info("开始上传文件到FTP,文件名称:" + fileName);
                System.out.println("开始上传文件到FTP,文件名称:" + fileName);
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置上传文件类型为二进制,否则将无法打开文件
                ftpClient.makeDirectory(servicePath);
                ftpClient.changeWorkingDirectory(servicePath);
                //设置为被动模式(如上传文件夹成功,不能上传文件,注释这行,否则报错refused:connect  )
                ftpClient.enterLocalPassiveMode();//设置被动模式,文件传输端口设置
                ftpClient.storeFile(fileName, inputStream);
                inputStream.close();
                ftpClient.logout();
                isSuccess = true;
                System.out.println(fileName + "文件上传到FTP成功");
                logger.info(fileName + "文件上传到FTP成功");
            } else {
                System.out.println("FTP连接建立失败");
                logger.error("FTP连接建立失败");
            }
        } catch (Exception e) {
            System.out.println(fileName + "文件上传到FTP出现异常");
            logger.error(fileName + "文件上传到FTP出现异常");
            logger.error(e.getMessage(), e);
        } finally {
            closeFtpClient(ftpClient);
            closeStream(inputStream);
        }
        return isSuccess;
    }

    public void closeStream(Closeable closeable) {
        if (null != closeable) {
            try {
                closeable.close();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    //改变目录路径
    public boolean changeWorkingDirectory(FTPClient ftpClient, String directory) {
        boolean flag = true;
        try {
            flag = ftpClient.changeWorkingDirectory(directory);
            if (flag) {
                logger.info("进入文件夹" + directory + " 成功!");

            } else {
                logger.info("进入文件夹" + directory + " 失败!开始创建文件夹");
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return flag;
    }

    //创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
    public boolean CreateDirecroty(FTPClient ftpClient, String remote) throws IOException {
        boolean success = true;

        String directory = remote;
        if (!remote.endsWith(File.separator)) {
            directory = directory + File.separator;
        }
        // 如果远程目录不存在,则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase(File.separator) && !changeWorkingDirectory(ftpClient, new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith(File.separator)) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf(File.separator, start);
            String path = "";
            String paths = "";
            while (true) {
                String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
                path = path + File.separator + subDirectory;
                if (!existFile(ftpClient, path)) {
                    if (makeDirectory(ftpClient, subDirectory)) {
                        changeWorkingDirectory(ftpClient, subDirectory);
                    } else {
                        logger.error("创建目录[" + subDirectory + "]失败");
                        changeWorkingDirectory(ftpClient, subDirectory);
                    }
                } else {
                    changeWorkingDirectory(ftpClient, subDirectory);
                }

                paths = paths + File.separator + subDirectory;
                start = end + 1;
                end = directory.indexOf(File.separator, start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }

    //判断ftp服务器文件是否存在
    public boolean existFile(FTPClient ftpClient, String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

    //创建目录
    public boolean makeDirectory(FTPClient ftpClient, String dir) {
        boolean flag = true;
        try {
            flag = ftpClient.makeDirectory(dir);
            if (flag) {
                logger.info("创建文件夹" + dir + " 成功!");

            } else {
                logger.info("创建文件夹" + dir + " 失败!");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return flag;
    }

    /**
     * 下载文件 *
     *
     * @param pathName FTP服务器文件目录 *
     * @param pathName 下载文件的条件*
     * @return
     */
    public boolean downloadFile(FTPClient ftpClient, String pathName, String targetFileName, String localPath) {
        boolean flag = false;
        OutputStream os = null;
        try {
            System.out.println("开始下载文件");
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathName);
            ftpClient.enterLocalPassiveMode();
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile file : ftpFiles) {
                String ftpFileName = file.getName();
                if (targetFileName.equalsIgnoreCase(ftpFileName.substring(0, ftpFileName.indexOf(".")))) {
                    File localFile = new File(localPath);
                    os = new FileOutputStream(localFile);
                    ftpClient.retrieveFile(file.getName(), os);
                    os.close();
                }
            }
            ftpClient.logout();
            flag = true;
            logger.info("下载文件成功");
        } catch (Exception e) {
            logger.error("下载文件失败");
            logger.error(e.getMessage(), e);
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return flag;
    }

    /*下载文件*/
    public InputStream download(String ftpFile, FTPClient ftpClient) throws IOException {
        String servicePath = String.format("%s%s%s", basePath, "/", ftpFile);
        logger.info("【从文件服务器获取文件流】ftpFile : " + ftpFile);
        if (StringUtils.isBlank(servicePath)) {
            throw new RuntimeException("【参数ftpFile为空】");
        }
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.enterLocalPassiveMode();
        ftpFile = new String(servicePath.getBytes("utf-8"), "iso-8859-1");
        return ftpClient.retrieveFileStream(ftpFile);
    }

    /**
     * 删除文件 *
     *
     * @param pathname FTP服务器保存目录 *
     * @param filename 要删除的文件名称 *
     * @return
     */
    public boolean deleteFile(String pathname, String filename) {
        boolean flag = false;
        FTPClient ftpClient = getFtpClient();
        try {
            logger.info("开始删除文件");
            if (ftpClient.isConnected()) {
                //切换FTP目录
                ftpClient.changeWorkingDirectory(pathname);
                ftpClient.enterLocalPassiveMode();
                ftpClient.dele(filename);
                ftpClient.logout();
                flag = true;
                logger.info("删除文件成功");
            } else {
                logger.info("删除文件失败");

            }
        } catch (Exception e) {
            logger.error("删除文件失败");
            logger.error(e.getMessage(), e);
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return flag;
    }

    public void closeFtpClient(FTPClient ftpClient) {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    public InputStream downloadFile(FTPClient ftpClient, String pathname, String filename) {
        InputStream inputStream = null;
        try {
            System.out.println("开始下载文件");
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathname);
            ftpClient.enterLocalPassiveMode();
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile file : ftpFiles) {
                if (filename.equalsIgnoreCase(file.getName())) {
                    inputStream = ftpClient.retrieveFileStream(file.getName());
                    break;
                }
            }
            ftpClient.logout();
            logger.info("下载文件成功");
        } catch (Exception e) {
            logger.error("下载文件失败");
            logger.error(e.getMessage(), e);
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return inputStream;
    }
}
4,**业务代码(controller,service)**
package com.idh.project.zdemo.controller;


import com.idh.project.zdemo.service.IFileDemoService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Map;

@Api(tags="测试Demo")
@RestController
@RequestMapping("/config/fileDemo")
public class FileDemoController {


    @Resource
    private IFileDemoService fileDemoService;

    @RequestMapping(value = "/uploadFile",method = RequestMethod.POST)
    public String upload(MultipartFile file){
        
        String s = fileDemoService.updatePhoto(file);
        return s;
    }

}

service


import com.idh.common.utils.file.FtpUtil;
import com.idh.project.zdemo.service.IFileDemoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@Service
public class IFileDemoServiceImpl implements IFileDemoService {

    @Override
    public String updatePhoto(MultipartFile file) {

        FtpUtil ftpUtil = new FtpUtil();

        //给起一个新的文件名称,防止名称重复
        String newname=new String();
       
        if(file!=null){
            //文件名称 = 时间戳 + 文件自己的名字;
            newname = System.currentTimeMillis()+file.getOriginalFilename();

            try {
                //图片上传,调用ftp工具类 image 上传的文件夹名称,newname 图片名称,inputStream
                boolean hopson = ftpUtil.uploadFileToFtp("scene", newname, file.getInputStream());
                if(hopson) {  //上传成功
                    // 文件信息入库
                   /* File file = new File();
                    file.setName(newname);
                    file.setSize(size);
                    file.setUrl(url);
                    file.setMassifId(massifId);
                    file.setPhoto(path + newname);
                    .....   等等业务处理
                    this.insert(dkPhoto);*/
                }
            } catch (Exception e) {
                e.printStackTrace();
                return "error";
            }
        }
        log.info("文件上传完成==============");
        return "sucess";
    }
}
5,测试,这里使用postman

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200805172931400.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dnZ2c5ODk4OTg=,size_16,color_FFFFFF,t_70)

注意:如果报错,请检查ftp的配置是否正确,IP端口以及账号密码是否争取,ftp服务是否正常。

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值