使用 FTP服务器 代替 OSS服务器实现文件上传

一、安装 vsftpd

  1、检查是否已经安装 vsftpd

    vsftpd -version

  2、如果未安装则使用以下命令安装(CentOS7)

    yum install -y vsftpd

  3、将FTP服务设置为开机自启动

    systemctl enable vsftpd.service

  4、启动FTP服务

    systemctl start vsftpd.service

二、配置 vsftpd

  1、为FTP服务创建一个Linux用户 (本篇文章用户名为 ftpuser)

    adduser ftpuser

  2、修改刚才创建的用户的密码

    passwd ftpuser

    然后输入两编新密码即可

  3、创建一个供FTP服务使用的文件目录(推荐切换为刚才创建的ftpuser,否则创建好后需要将文件目录的拥有者修改为ftpuser)

    切换为 ftpuser 用户  

      su ftpuser

    创建文件目录

      mkdir /var/ftp/ftpuser

    创建测试文件(该测试文件用于FTP客户端访问FTP服务器时使用)

      vim /var/ftp/ftpuser/test.txt
      点击 i 随便写一些什么东西 :wq 保存后退出

  4、修改vsftpd.conf配置文件

    打开vsftpd的配置文件

      vim /etc/vsftpd/vsftpd.conf

    按 i 进入编辑模式

    具体的配置参数说明如下(除下面提及的参数,其他参数保持默认值即可)

#配置文件修改以下参数
#是否允许匿名访问
anonymous_enable=NO
#是否允许使用本地帐户进行 FTP 用户登录验证
local_enable=YES
#监听IPv4 sockets
listen=YES
#关闭监听IPv6 sockets
#listen_ipv6=YES
#是否限定用户在其主目录下(NO 表示允许切换到上级目录)
chroot_local_user=YES

#在配置文件末添加以下参数
#设置本地用户登录后所在目录
local_root=/var/ftp/ftpuser
#将用户限制在主目录 chroot_local_user=YES
#是否启用限制用户的名单(注释掉为禁用)
#chroot_list_enable
=YES
#指定例外用户列表文件,列表中用户不被锁定在主目录 chroot_list_file
=/etc/vsftpd/chroot_list
#开启被动模式 pasv_enable=YES allow_writeable_chroot=YES
pasv_address=<FTP服务器IP地址> #设置被动模式下,建立数据传输可使用的端口范围的最小值。 #建议把端口范围设置在一段比较高的范围内,例如50000~50010,有助于提高访问FTP服务器的安全性 pasv_min_port=<port number> #设置被动模式下,建立数据传输可使用的端口范围的最大值 pasv_max_port=<port number>

    按Esc退出编辑模式,然后输入:wq并回车以保存并关闭文件

  5、创建chroot_list文件,并在文件中写入例外用户名单(注意:没有例外用户时,也必须创建chroot_list文件,内容可为空)

    运行以下命令,创建chroot_list文件

    vim /etc/vsftpd/chroot_list

    按i进入编辑模式

    输入例外用户名单,此名单中的用户不会被锁定在主目录,可以访问其他目录(注意:用户列表文件(一行一个用户))

    按Esc退出编辑模式,然后输入:wq并回车以保存并关闭文件

  6、运行以下命令重启vsftpd服务。

   systemctl restart vsftpd.service

三、客户端测试

  在本地主机,打开这台电脑

  在地址栏中输入ftp://<FTP服务器IP地址>:FTP端口   例:111:111:111:111:21

  在弹出的登录身份对话框中,输入已设置的FTP用户名和密码,然后单击登录

  登录后,您可以查看到FTP服务器指定目录下的文件

 四、使用tomcat实现文件查看功能

  本文使用的是docker中的tomcat容器实现挂载目录来完成的,如果不想使用docker的话则将vsftpd.conf配置文件中设置本地用户登录后所在目录修改为tomcat中的/usr/local/tomcat/webapps/ROOT 文件夹下即可

  1、docker 安装tomcat

1、拉取镜像
docker pull tomcat:8.5.40
2、创建tomcat容器
docker run -d -p 9080:8080 --name tomcat-resoure -v /var/ftp/ftpuser/:/usr/local/tomcat/webapps/ROOT --restart=always tomcat:8.5.40
-p 对外开放的端口
-v 将ROOT挂载到本地用户登录后所在目录
--restart=always 自启动
3、通过docker ps查看运行状态

 4、http:/IP:9080/text.txt 查看即可

五、后台文件上传(SpringBoot)

  1、yml 文件配置

  

  2、调用类中获取yml中的配置

   

  3、创建FTP上传工具类FtpUtil

    在 pom.xml 中添加依赖

        <!-- 用于 FTP 服务器文件上传 -->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.6</version>
        </dependency>
        <!-- lombok 简化代码的书写与日志打印 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>

 

package org.hbjy.util;

import lombok.extern.slf4j.Slf4j;
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 java.io.*;

@Slf4j
public class FtpUtil {
    public static FTPClient ftpClient = null;

    /**
     * 初始化ftp服务器
     */
    public static void initFtpClient(String hostname,String username,String password,Integer port) {
        ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");
        try {
            //连接ftp服务器
            ftpClient.connect(hostname, port);
            //登录ftp服务器
            ftpClient.login(username, password);
            //是否成功登录服务器
            int replyCode = ftpClient.getReplyCode();
            if(!FTPReply.isPositiveCompletion(replyCode)){
                ftpClient.disconnect();
                log.error("登录FTP服务失败!返回码为[{}]", replyCode);
            } else {
                log.info("登录FTP服务成功!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     * @param pathname ftp服务保存地址
     * @param fileName 上传到ftp的文件名
     * @param inputStream 输入文件流
     */
    public static boolean uploadFile(String hostname, String username, String password, Integer port, String pathname, String fileName, InputStream inputStream){
        boolean flag = false;
        try{
            log.info("开始上传文件");
            initFtpClient(hostname,username,password,port);
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            CreateDirecroty(pathname);
            ftpClient.makeDirectory(pathname);
            ftpClient.setControlEncoding("utf-8");
            ftpClient.storeFile(fileName, inputStream);
            log.info("上传结束");
            inputStream.close();
            ftpClient.logout();
            flag = true;
            log.info("上传文件成功");

        }catch (Exception e) {
            log.error("上传文件失败");
            e.printStackTrace();
        }finally{
            if(ftpClient.isConnected()){
                try{
                    ftpClient.disconnect();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
            if(null != inputStream){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }
    //改变目录路径
    public static boolean changeWorkingDirectory(String directory) {
        boolean flag = true;
        try {
            flag = ftpClient.changeWorkingDirectory(directory);
            if (flag) {
                log.info("进入文件夹" + directory + " 成功!");
            } else {
                log.error("进入文件夹" + directory + " 失败!开始创建文件夹");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return flag;
    }

    //创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
    public static boolean CreateDirecroty(String remote) throws IOException {
        boolean success = true;
        String directory = remote + "/";
        // 如果远程目录不存在,则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf("/", start);
            String path = "";
            String paths = "";
            while (true) {
                String subDirectory = new String(remote.substring(start, end).getBytes("UTF-8"), "iso-8859-1");
                path = path + "/" + subDirectory;
                if (!existFile(path)) {
                    if (makeDirectory(subDirectory)) {
                        changeWorkingDirectory(subDirectory);
                    } else {
                        log.error("创建目录[" + subDirectory + "]失败");
                        changeWorkingDirectory(subDirectory);
                    }
                } else {
                    changeWorkingDirectory(subDirectory);
                }

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

    //判断ftp服务器文件是否存在
    public static boolean existFile(String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }
    //创建目录
    public static boolean makeDirectory(String dir) {
        boolean flag = true;
        try {
            flag = ftpClient.makeDirectory(dir);
            if (flag) {
                log.info("创建文件夹" + dir + " 成功!");

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

    /** * 下载文件 *
     * @param pathname FTP服务器文件目录 *
     * @param filename 文件名称 *
     * @param localpath 下载后的文件路径 *
     * */
    public static  boolean downloadFile(String hostname,String username,String password,Integer port,String pathname, String filename, String localpath){
        boolean flag = false;
        OutputStream os=null;
        try {
            log.info("开始下载文件");
            initFtpClient(hostname,username,password,port);
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathname);
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for(FTPFile file : ftpFiles){
                if(filename.equalsIgnoreCase(file.getName())){
                    File localFile = new File(localpath + "/" + file.getName());
                    os = new FileOutputStream(localFile);
                    ftpClient.retrieveFile(file.getName(), os);
                    os.close();
                }
            }
            ftpClient.logout();
            flag = true;
            log.info("下载文件成功");
        } catch (Exception e) {
            log.error("下载文件失败");
            e.printStackTrace();
        } finally{
            if(ftpClient.isConnected()){
                try{
                    ftpClient.disconnect();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
            if(null != os){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /** * 删除文件 *
     * @param pathname FTP服务器保存目录 *
     * @param filename 要删除的文件名称 *
     * */
    public static boolean deleteFile(String hostname,String username,String password,Integer port,String pathname, String filename){
        boolean flag = false;
        try {
            log.info("开始删除文件");
            initFtpClient(hostname,username,password,port);
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathname);
            ftpClient.dele(filename);
            ftpClient.logout();
            flag = true;
            log.info("删除文件成功");
        } catch (Exception e) {
            log.error("删除文件失败");
            e.printStackTrace();
        } finally {
            if(ftpClient.isConnected()){
                try{
                    ftpClient.disconnect();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }
}

 

  4、上传文件到 FTP 服务器

  

 

 

   5、将地址返回到前端,用户提交时保存到数据库即可

posted @ 2022-07-21 15:35  柠檬s  阅读(92)  评论(0)    收藏  举报