fastDFS整合springboot Demo演练

基本操作

  • 启动

    // 服务器启动
    fdfs_trackerd /etc/fdfs/tracker.conf
    //跟踪器启动
    fdfs_storaged /etc/fdfs/storage.conf
    
  • 查看启动情况

    ps -ef | grep fdfs
    
  • 重启

    fdfs_trackerd /etc/fdfs/tracker.conf restart
    fdfs_storaged /etc/fdfs/storage.conf restart
    
  • 查看数据存储信息

    //文件地址对应配置文件的目录地址
    ll /fastdfs/storage/files/data/00/00/
    
  • 文件上传测试

    //在任意目录下创建txt文件
    echo "Hello,FastDFS" > a.txt
    //上传文件到服务器
    fdfs_test /etc/fdfs/client.conf upload 文件路径
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-axeU9oLe-1639041114593)(E:/Typroa图片/image-20211208150157674.png)]

  • 数据删除

    fdfs_delete_file /etc/fdfs/client.conf (group_name)/(remote_filename)
    

    group_name:当前文件的组地址

    remote_filename:当前文件的名字

  • 关闭

    fdfs_trackerd /etc/fdfs/tracker.conf stop
    fdfs_storaged /etc/fdfs/storage.conf stop
    
/usr/local/nginx_fdf/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf

整合nginx实现外网访问

  • fastDFS官网下载fastdfs-nginx-module_v1.16.tar.gz上传 解压

  • 编辑配置文件 进入文件的当前路径 进行修改 vim config

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eEyM4OFY-1639041114594)(E:/Typroa图片/image-20211209101246012.png)]

将第一行的local删除即可

  • 将FastDFS-nginx-module/src下的mod_fastdfs.conf拷贝至/etc/fdfs/下
cp /usr/local/tmp/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
  • 修改conf
vim /etc/fdfs/mod_fastdfs.conf

修改 bath_path、tracker_server、url_have_group_name、store_path0

第一个地址任意、第二个修改为当前服务器的ip地址、第三个改为true 访问时需要带group号、第四个改为storage存放文件的file路径

nginx安装

安装依赖

yum install -y gcc gcc-c++ make libtool wget pcre pcre-devel zlib zlib-devel openssl openssl-devel

创建文件夹

mkdir -p /var/temp/nginx/client

上传tar解压包 运行解压命令

完成之后 运行下列代码

./configure \
--prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/opt/fastdfs-nginx-module/src

module的路径是存放fastdfs_module插件的src路径

运行完之后 查看nginx目录 会多出来makefile的文件

第一遍 执行make命令编译 第二遍执行make install 命令 安装

安装完成之后 修改conf文件

vim /usr/local/nginx/conf/nginx.conf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L5XAYj2J-1639041114595)(E:/Typroa图片/image-20211209102116818.png)]

启动nginx

/usr/local/nginx/sbin/nginx

设置开机启动

vim /etc/rc.d/rc.local

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dPC0IWKy-1639041114596)(E:/Typroa图片/image-20211209102200375.png)]

最重要一点

​ 关闭防火墙 否则无法访问

systemctl stop firewalld

然后测试即可

springboot整合fastDFS

  • 首先编写配置类fastdfs_client.conf 放在resources目录下即可
connect_timeout = 2
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = FastDFS1234567890

tracker_server = 192.168.171.224:22122   这里要换成自己的服务器端口

connection_pool.enabled = true
connection_pool.max_count_per_entry = 500
connection_pool.max_idle_time = 3600
connection_pool.max_wait_time_in_ms = 1000

  • 然后进行测试即可
  @Test
    void down() {
        try {
            // 1.加载配置文件,默认去classpath下加载
            ClientGlobal.init("fdfs_client.conf");
            // 2.创建TrackerClient对象
            TrackerClient trackerClient = new TrackerClient();
            // 3.创建TrackerServer对象
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            // 4.创建StorageServler对象
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            // 5.创建StorageClient对象,这个对象完成对文件的操作
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            // 6.下载文件
            String fileName="M00/00/00/wKir4GGwdC6ACJQTAABjNFGdk2o632.png";
            String groppName="group1";
            byte[] bytes = storageClient.download_file(groppName, fileName);
            System.out.println(bytes);

            //获取当前路径 下载的文件输出到桌面  也可以将其替换成任意地址
            File desktopDir = FileSystemView.getFileSystemView() .getHomeDirectory();
            String desktopPath = desktopDir.getAbsolutePath();
            // 7.输出到指定位置的文件名
            File file = new File(desktopPath+"\\3.png");
            FileOutputStream fileOutputStream=new FileOutputStream(file);//窗机输出流
            fileOutputStream.write(bytes);//写入数据
            fileOutputStream.close();//关闭输出流
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }

    }
    @Test
    void upLoad(){
        try {
            // 1.加载配置文件,默认去classpath下加载
            ClientGlobal.init("fdfs_client.conf");
            // 2.创建TrackerClient对象
            TrackerClient trackerClient = new TrackerClient();
            // 3.创建TrackerServer对象
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            // 4.创建StorageServler对象
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            // 5.创建StorageClient对象,这个对象完成对文件的操作
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            // 6.上传文件(第一个参数:本地文件路径、第二个参数:上传文件的后缀、第三个参数:文件信息)
            String[] uploadArray = storageClient.upload_file("G:\\test.png", "png", null);
            for (String str : uploadArray) {
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }

    }
    @Test
    void delete(){
        try {
            // 1.加载配置文件,默认去classpath下加载
            ClientGlobal.init("fdfs_client.conf");
            // 2.创建TrackerClient对象
            TrackerClient trackerClient = new TrackerClient();
            // 3.创建TrackerServer对象
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            // 4.创建StorageServler对象
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            // 5.创建StorageClient对象,这个对象完成对文件的操作
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            // 6.删除文件(返回0表示成功,其它均表示失败)和上传文件一个道理 输入组名和服务器中的文件名
            int num = storageClient.delete_file("group1", "M00/00/00/wKir4GGxd9iAar6rAAOHYHzsk8w050.png");
            System.out.println(num);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

测试过程中发现 许多步骤都是固定的 ,唯一不变的只有进行具体操作时调用的方法,因此再此基础上整理出工具类以供使用

FastDFSUtil

package com.llf.up_and_down.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;

import java.io.*;

/**
 * @Author llf
 * @Date 2021/12/9 13:57
 * @Version 1.0
 */public class FastDFSUtils {



    /**
     * FastDFS 分布式文件系统 Java 客户端工具类
     * 具体功能:文件上传、下载、替换、删除、查询文件元数据、查看文件详情
     */


        // 获取配置文件地址
        private static final String CONF_FILENAME = Thread.currentThread()
                .getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
        // Storage 存储服务器客户端
        private static StorageClient storageClient = null;

        static {
            try {
                // 加载配置文件
                ClientGlobal.init("fdfs_client.conf");
                // 初始化 Tracker 客户端
                TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
                // 初始化 Tracker 服务端
                TrackerServer trackerServer = trackerClient.getTrackerServer();
                // 初始化 Storage 服务端
                StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
                // 初始化 Storage 客户端
                storageClient = new StorageClient(trackerServer, storageServer);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
        }

        /**
         * 文件上传
         *
         * @param inputStream 上传的文件的字节输入流
         * @param fileName    上传的文件的原始名
         * @return
         */
        public static String[] uploadFile(InputStream inputStream, String fileName) {
            try {
                // 准备字节数组
                byte[] fileBuff = null;
                // 文件元数据
                NameValuePair[] metaList = null;
                if (inputStream != null) {
                    // 查看文件的长度
                    int len = inputStream.available();
                    // 初始化元数据数组
                    metaList = new NameValuePair[2];
                    // 第一组元数据,文件的原始名称
                    metaList[0] = new NameValuePair("file_name", fileName);
                    // 第二组元数据,文件的长度
                    metaList[1] = new NameValuePair("file_length", String.valueOf(len));
                    // 创建对应长度的字节数组
                    fileBuff = new byte[len];
                    // 将输入流中的字节内容,读到字节数组中
                    inputStream.read(fileBuff);
                }
            /*
                上传文件。
                参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据
             */
                String[] fileids = storageClient.upload_file(fileBuff, getFileExt(fileName), metaList);
                inputStream.close();
                return fileids;
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         * 文件上传
         *
         * @param file     上传的文件
         * @param fileName 上传的文件的原始名
         * @return
         */
        public static String[] uploadFile(File file, String fileName) {
            try (
                    FileInputStream fis = new FileInputStream(file)) {
                fis.close();
                return uploadFile(fis, fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * 获取文件后缀名(不带点)
         *
         * @param fileName
         * @return 如:"jpg" or ""
         */
        private static String getFileExt(String fileName) {
            if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
                return "";
            }
            return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
        }

        /**
         * 获取文件详情
         *
         * @param groupName      组/卷名,默认值:group1
         * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
         * @return 文件详情
         */
        public static FileInfo getFileInfo(String groupName, String remoteFileName) {
            try {
                return storageClient.get_file_info(groupName == null ? "group1" : groupName, remoteFileName);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         * 获取元数据
         *
         * @param groupName      组/卷名,默认值:group1
         * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
         * @return 文件的元数据数组
         */
        public static NameValuePair[] getMetaData(String groupName, String remoteFileName) {
            try {
                // 根据组名和文件名通过 Storage 客户端获取文件的元数据数组
                return storageClient.get_metadata(groupName == null ? "group1" : groupName, remoteFileName);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         * 文件下载
         *
         * @param groupName      组/卷名,默认值:group1
         * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
         * @return 文件的字节输入流
         */
        public static InputStream downloadFile(String groupName, String remoteFileName) {
            try {
                // 根据组名和文件名通过 Storage 客户端获取文件的字节数组
                byte[] bytes = storageClient.download_file(groupName == null ? "group1" : groupName, remoteFileName);
                // 返回字节流对象
                InputStream inputStream = new ByteArrayInputStream(bytes);
                inputStream.close();
                return inputStream;
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         * 文件删除
         *
         * @param groupName      组/卷名,默认值:group1
         * @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
         * @return 0为成功,非0为失败
         */
        public static int deleteFile(String groupName, String remoteFileName) {
            int result = -1;
            try {
                // 根据组名和文件名通过 Storage 客户端删除文件
                result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
            return result;
        }

        /**
         * 修改一个已经存在的文件
         *
         * @param oldGroupName 旧组名
         * @param oldFileName  旧文件名
         * @param file         新文件
         * @param fileName     新文件名
         * @return
         */
        public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) {
            // 先上传
            String[] fileids = uploadFile(file, fileName);
            if (fileids == null) {
                return null;
            }
            // 再删除
            int delResult = deleteFile(oldGroupName, oldFileName);
            if (delResult != 0) {
                return null;
            }
            return fileids;
        }

    }


配合web实现demo

  • 前端实现
<form enctype="multipart/form-data" method="post" action="/upLoadImg">
<input type="file" id="info" name="file" >
    <input type="submit" value="上传" />
</form>

一个简单的input输入框 这种方式是最容已实现的

  • 后端处理
 @PostMapping("/upLoadImg")
    public String upLoadImg(MultipartFile file,Model model){
        try {
            /* 获取上传文件名字*/
            String filename = file.getOriginalFilename();
            /* 截取文件扩展名 */
            String extName = filename.substring(filename.lastIndexOf(".") + 1);
            /* 使用fastdfs工具类上传图片 */
            String[] file1 = FastDFSUtils.uploadFile(file.getInputStream(), filename);
            StringBuffer buffer = new StringBuffer();
            //这里设置为fastdfs服务器的地址
            buffer.append("http://192.168.171.224/");
            for (String s : file1) {
                // 为组名后面添加 / 与文件名拼接
               if (!s.endsWith("png")){
                   buffer.append(s+"/");
               }else {
                   buffer.append(s);
               }
                System.out.println(s);
            }
            String url=String.valueOf(buffer);
           model.addAttribute("url",url);


        } catch (Exception e) {
            e.printStackTrace();

        }

        return "image";
    }

返回新的页面 拿到url的值 进行页面渲染

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<img th:src="@{${url}}" alt="刚上传的图片">
<span th:text="${url}"></span>
</body>
</html>

在这里插入图片描述

Utils工具类的代码直接复制 修改一下配置文件的地址就可以直接使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FastDFS是一个开源的分布式文件系统,可以实现文件存储和查找。而Spring Boot是一个基于Spring Framework的快速开发框架。 在整合FastDFSSpring Boot时,我们可以使用Token来实现权限的控制和安全性。 首先,我们可以使用Spring Boot提供的Token机制来验证用户的身份。当用户登录时,系统会生成一个Token,并将其返回给客户端。客户端在后续的请求中,需要将Token放在请求头中进行验证。这可以防止未经授权的用户访问受限资源。 其次,我们可以将FastDFS与Token进行整合。当用户上传文件时,系统会生成一个唯一的Token,并将Token和文件的元数据存储在数据库中。在用户下载文件时,系统会验证Token的有效性,并根据Token从数据库中获取文件的元数据,然后使用FastDFS进行文件的查找和传输。这样可以确保只有拥有有效Token的用户才能下载文件,增加了系统的安全性。 还可以通过Token来限制用户的操作权限。对于不同的用户角色,可以分配不同的Token权限。比如,管理员可以进行文件的上传和删除操作,普通用户只能进行文件的下载操作。这样可以实现对系统资源的精细权限控制。 综上所述,通过整合FastDFSSpring Boot的Token机制,我们可以实现对文件系统的权限控制和安全性增强。用户通过验证Token来访问受限资源,同时根据Token的权限来限制用户的操作行为。这样能够提高系统的安全性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值