Docker、CentOS7 安装 FTP 服务并与 SpringBoot 集成

873 阅读3分钟

一、CentOS7 安装 FTP 服务

以前,如果要完成譬如上传头像功能,需要访问后端接口,将头像信息上传到前端项目中(也就是我们自己的服务器上),这是不合理的,需要有一个专门的 文件服务器 来存储。就需要用 FTP 来搭建一个 文件服务器

1:安装 vsftpd

yum -y install vsftpd

2:关闭匿名访问

可以不关,但是关了以后就必须得输入用户名和密码才能访问

vim /etc/vsftpd/vsftpd.conf

将anonymous_enable的值改为NO

image.png

3:启动服务

systemctl start vsftpd.service

4:查看服务状态

systemctl status vsftpd.service

如果结果中包含 active(running) 则表示启动成功。

启动成功后,需要通过外部去访问 FTP 服务器,需要开放端口。

5:开放端口访问

firewall-cmd --zone=public --add-port=21/tcp --permanent
firewall-cmd --zone=public --add-port=1025-65535/tcp --permanent
systemctl restart firewalld
​
firewall-cmd --list-ports

Add:直接在 Windows 上访问 Linux

image.png

需要新建用户,来操作 FTP。

ROOT 用户不能用于 FTP 服务器登录

6:新建一个用户,测试操作 FTP

adduser user-file
passwd user-file

上传的文件,会保存在访问用户的工作空间下:/home/user-file

image.png

登录,如果提示错误:

image.png

image.png

chmod -R 777 /home/user-file/

二、SpringBoot上传文件到Linux的FTP文件服务器

1:pom 依赖

<!-- FTP上传文件组件 -->
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.3</version>
</dependency>

2:编写一个用于 FTP 操作的工具类

package com.du.ftptest.utils;
​
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Value;
​
import java.io.IOException;
import java.io.InputStream;
​
public class FtpUtil {
​
    // FTP服务器IP地址
    // @Value("${ftp.service.address}")
    private static final String FTP_SERVICE_ADDRESS = "106.225.xxx.xxx";
​
    // 端口号
    // @Value("${ftp.service.port}")
    private static final int FTP_SERVICE_PORT = 21;
​
    // 用户名
    // @Value("${ftp.service.username}")
    private static final String FTP_SERVICE_USERNAME = "duruikun-file";
​
    // 密码
    // @Value("${ftp.service.password}")
    private static final String FTP_SERVICE_PASSWORD = "duruikun.123";
​
    // 附件路径
    // @Value("${ftp.service.basepath}")
    private static final String FTP_SERVICE_BASEPATH = "/home/duruikun-file/files";
​
    public static boolean uploadFile(String fileName, InputStream input) {
        boolean success = false;
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(FTP_SERVICE_ADDRESS, FTP_SERVICE_PORT);
            ftp.login(FTP_SERVICE_USERNAME, FTP_SERVICE_PASSWORD);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return false;
            }
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.makeDirectory(FTP_SERVICE_BASEPATH);
            ftp.changeWorkingDirectory(FTP_SERVICE_BASEPATH);
            ftp.enterLocalPassiveMode();
            ftp.storeFile(fileName, input);
            input.close();
            ftp.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }
}

3:上传文件接口

@RestController
public class UserController {

    @Resource
    private UserService userService;
​
    @PostMapping("addUser")
    public String addUser(User user, @RequestParam("headPic") MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            String filename = file.getOriginalFilename();
            String suffix = filename.substring(filename.lastIndexOf("."));
            String finalName = UUID.randomUUID() + suffix;
            boolean flag = FtpUtil.uploadFile(finalName, inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "成功";
    }
}

4:postman 测试文件上传

image.png

三、Docker 部署 FTP

1:docker search

docker search vsftpd

2:docker pull

docker pull fauria/vsftpd

3: docker run

docker run -d -p 20:20 -p 21:21 -p 8800-8899:8800-8899 -v /home/dockerData/ftpData:/home/vsftpd -e FTP_USER=duruikun -e FTP_PASS=123456 -e PASV_ADDRESS=127.0.0.1 -e PASV_MIN_PORT=8800 -e PASV_MAX_PORT=8899 --name vsftpd --restart=always fauria/vsftpd

如果8848与nacos冲突:

docker run -d -p 20:20 -p 21:21 -p 8800-8847:8800-8847 -p 8849-8899:8849-8899 -v /home/dockerData/ftpData:/home/vsftpd -e FTP_USER=duruikun -e FTP_PASS=123456 -e PASV_ADDRESS=127.0.0.1 -e PASV_MIN_PORT=8800 -e PASV_MAX_PORT=8899 --name vsftpd --restart=always fauria/vsftpd
-d 指定容器运行于前台还是后台,默认为false
-p 端口映射 容器暴露的端口:内部真实端口
-v 容器挂载存储卷(暴露给外部的存储卷):挂载到容器的某个目录(内部真实目录)
-e 指定环境变量,容器中可以使用该环境变量
FTP_USER ftp账户
FTP_PASS ftp秘钥
PASV_ADDRESS 宿主机ip
PASV_MIN_PORT ftp被动模式下的最小端口
PASV_MAX_PORT ftp被动模式下的最大端口
–name 指定容器的名字
–restart 指定容器停止后的重启策略:no:容器退出时不重启 on-failure:容器故障退出(返回值非零)时重启 always:容器退出时总是重启
fauria/vsftpd 要部署到容器中得镜像
​
最后需要在服务器端开启 20-21 8800-8899 端口

image.png

end:测试成功

image.png