分布式文件存储与数据缓存 FastDFS(二)

简介: 分布式文件存储与数据缓存 FastDFS(二)

四、SpringBoot操作FastDFS实现文件上传(基本版)

由GitHub大牛tobato在原作者YuQing与yuqih发布的JAVA客户端基础上进行了大量重构工作,并于GitHub上发布了FastDFS-Client1.26.5。

主要特性

  1. 对关键部分代码加入了单元测试,便于理解与服务端的接口交易,提高接口质量
  2. 将以前对byte硬解析风格重构为使用对象+注解的形式,尽量增强了代码的可读性
  3. 支持对服务端的连接池管理
  4. 支持上传图片时候检查图片格式,并且自动生成缩略图
  5. 在SpringBoot当中自动导入依赖

1、创建springboot项目(2.7.0),导入FastDFS依赖jar

<dependency>
  <groupId>com.github.tobato</groupId>
  <artifactId>fastdfs-client</artifactId>
  <version>1.26.5</version>
</dependency>

2、添加配置

####分布式文件系统配置###########
fdfs:
  so-timeout: 1500
  connect-timeout: 600
  thumb-image:       #缩略图生成参数
    width: 150
    height: 150
  tracker-list:       #TrackerList参数,支持多个
    - 192.168.66.100:22122
   # - 192.168.66.101:22122

3、编写测试类实现文件上传和文件下载

package com.zj;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.*;
@SpringBootTest
class FastdfsApplicationTests {
    //通过FastDFS的客户端对象完成对文件系统的操作
    @Resource
    private FastFileStorageClient fastFileStorageClient;
    //测试上传文件
    @Test
    public void upload() throws FileNotFoundException {
        //1.先读取本地文件
        File file = new File("D:\\aaa.jpg");
        //2.创建传输文件输入流
        FileInputStream fileInputStream = new FileInputStream(file);
        //3.文件上传
        /*
         * 参数一:文件输入流
         * 参数二:文件大小
         * 参数三:文件拓展名
         * 参数四:描述文件的元数据(指定文件上传的位置)
         */
        StorePath storePath = fastFileStorageClient.uploadFile(fileInputStream, file.length(), "jpg", null);
        //4.将卷名和文件名一起打印
        System.out.println("上传文件的地址:"+storePath.getFullPath());
        System.out.println("文件卷名:"+storePath.getGroup());
        System.out.println("文件名:"+storePath.getPath());
    }
    //文件下载
    @Test
    public void download() throws IOException {
       //1.下载文件
        /*
         * 参数一:文件处于存储节点的卷名
         * 参数二:文件在存储节点的文件名
         * 参数三:下载的回调函数
         */
        byte[] downloadFile = fastFileStorageClient.downloadFile("group1", "M00/00/00/wKhCZGS2WGaAYKOuADcAPt_yJDw957.jpg", new DownloadByteArray());
         //2.创建文件输出流,并指定文件下载的位置
        FileOutputStream fileOutputStream = new FileOutputStream("d:\\aaa.jpg");
         //3.将文件输出流写文件到磁盘
        fileOutputStream.write(downloadFile);
        //4.刷新
        fileOutputStream.flush();
        //5.关闭流
        fileOutputStream.close();
    }
}

五、spring boot整合FastDFS实现文件上传(完整版)

1、引入Thymeleaf视图解析器和文件上传客户端对象

<!--fastdfs-->
        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

注意:

使用wangeditor富文本编辑器的前提是引入Thymeleaf模板。

2、通过CDN在前端页面引入wangEditor富文本编辑器

<script type="text/javascript" src="https://unpkg.com/wangeditor/dist/wangEditor.min.js"></script>

3、创建编辑器基本骨架

<div id="div1">
    <p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<script type="text/javascript">
    const E = window.wangEditor;
    const editor = new E('#div1')
    editor.create();
</script>

4、创建文件上传的Controller控制器

package com.zj.controller;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
@RestController
public class uploadController {
    @Resource
    private FastFileStorageClient fastFileStorageClient;
    //图片上传
    @PostMapping("/upload")
    public void upload(MultipartFile file) throws IOException {
      //1.判断文件是否为空
        if(file != null){
            //2.获取上传的图片的名字
            String originalFilename = file.getOriginalFilename();
            //3.获取上传的图片的扩展名
            String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            //4.上传图片
            StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), suffix, null);
            System.out.println("上传的文件的路径:"+storePath.getFullPath());
            //5.上传的文件路径需要保存到数据库中
            //……
        }
    }
}

文件上传的请求方式必须是post

5、完整的index.html页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <script type="text/javascript" src="https://unpkg.com/wangeditor/dist/wangEditor.min.js"></script>
</head>
<body>
<div id="div1">
    <p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<script type="text/javascript">
    const E = window.wangEditor;
    const editor = new E('#div1');
    //指定文件上传的服务路径
    editor.config.uploadImgServer = "/upload";
    //文件参数名
    editor.config.uploadFileName = "file";
    //限制文件上传的大小和类型 2M
    editor.config.uploadImgMaxSize = 2 * 1024 * 1024;
    //文件上传的类型
    editor.config.uploadImgAccept = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
    editor.create();
</script>
</body>
</html>

6、启动项目,上传图片即可

六、FastDFS整合Nginx

 Nginx服务器是一个高性能的web服务器与反向代理服务器。

FastDFS集成Nginx的2个原因

  1. 为分布式文件系统提供Http服务支持

通过Nginx的web服务代理访问分布式文件系统的存储节点,从而实现通过http请求访问存储节点资源。

注意:

src 属性值图像文件的 URL。也就是引用该图像的文件的的绝对路径或相对路径。

 2.解决复制延迟问题

由于FastDFS的同卷的存储节点之间需要同步,当文件尚未同步完成时,访问请求到达改节点,获取的数据将是未同步完的不完整数据,即为复制延迟问题。通过Nginx检测请求的存储节点的数据,若该存储节点的数据尚未同步完成,则将请求转发至数据的原存储节点,从而解决复制延迟问题。

环境搭建

下载Fastdfs的Nginx模块包

#选择安装位置
cd /usr/local
#下载文件(或者使用本文章已经下载好的文件)
wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz
#解压文件
tar -zxvf V1.22.tar.gz

在ginx-1.20.2目录下安装Nginx依赖文件

yum install -y gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel gd-devel epel-release

配置Nginx服务器

#建立Makefile文件,检查Linux系统环境以及相关的关键属性。添加fastdfs-nginx-module-1.22模块到nginx
./configure --add-module=/usr/local/fastdfs-nginx-module-1.22/src/
#编译项目,主要将gcc源代码编译成可执行的目标文件
make
#根据上一步骤编译完成的数据安装到预定的目录中。之前安装过ngxin的话不需要再安装
make install

注意:

  • –add-module:为nginx添加一个fastdfs-nginx-module模块,值为该模块在当前系统的路径
  • –prefix:指定nginx安装位置

将Fastdfs软件包里面的http.conf和mime.types拷贝到/etc/fdfs目录下

cp /usr/local/fastdfs-6.06/conf/mime.types /etc/fdfs/
cp /usr/local/fastdfs-6.06/conf/http.conf /etc/fdfs/

配置Nginx的fastdfs模块,并编辑文件

#拷贝文件
[root@localhost opt]cp /usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs/
[root@localhost fdfs] vim mod_fastdfs.conf
#保存日志目录
base_path=/data/fastdfs/storage   
#tracker 服务器的 IP 地址以及端口号
tracker_server=192.168.66.100:22122 
#文件url中是否有group 名
url_have_group_name = true      
#存储路径
store_path0=/data/fastdfs/storage  
group_count = 1            #设置组的个数
#然后在末尾添加分组信息,目前只有一个分组,就只写一个
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/data/fastdfs/storage

配置Nginx

server {
  listen    80;
  server_name  localhost;
  location ~ /group[1-3]/M00 {
    alias /data/fastdfs/storage/data;
     ngx_fastdfs_module;
   }
  # 根目录下返回403
  location = / {
     return 403;
   }
  # log file
  access_log  logs/img_access.log access;
}

启动Ningx服务

# 进入sbin目录
[root@tracker nginx]# cd sbin/
# 启动服务 -c:指定配置文件
[root@tracker sbin]# ./nginx -c /usr/local/nginx/conf/nginx.conf

查看服务启动情况

[root@tracker sbin]# ps -ef | grep nginx

启动追踪服务与存储节点服务

[root@tracker sbin]# fdfs_trackerd /etc/fdfs/tracker.conf start
[root@tracker sbin]# fdfs_storaged /etc/fdfs/storage.conf start

上传图片测试

将图片上传至linux系统后,使用指令上传至分布式文件系统

[root@localhost /]# fdfs_upload_file /etc/fdfs/client.conf pdx.jpg
group1/M00/00/00/wKhCZGS6zneAUxGKAANsTCZQKGY401.jpg

通过浏览器远程访问

http://192.168.66.100/group1/M00/00/00/wKhCZGS6zneAUxGKAANsTCZQKGY401.jpg


相关文章
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
2月前
|
缓存 NoSQL Java
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
缓存与分布式锁、Redisson分布式锁、缓存数据一致性【必须满足最终一致性】
118 14
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
|
1月前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
56 4
|
1月前
|
存储 开发框架 .NET
C#语言如何搭建分布式文件存储系统
C#语言如何搭建分布式文件存储系统
67 2
|
28天前
|
SQL NoSQL MongoDB
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
39 0
|
1月前
|
存储 分布式计算 监控
C# 创建一个分布式文件存储系统需要怎么设计??
C# 创建一个分布式文件存储系统需要怎么设计??
31 0
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
4月前
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
3月前
|
缓存 NoSQL 关系型数据库
(八)漫谈分布式之缓存篇:唠唠老生常谈的MySQL与Redis数据一致性问题!
本文来聊一个跟实际工作挂钩的老生常谈的问题:分布式系统中的缓存一致性。
151 11
|
4月前
|
存储 缓存 NoSQL
高并发架构设计三大利器:缓存、限流和降级问题之Redis用于搭建分布式缓存集群问题如何解决
高并发架构设计三大利器:缓存、限流和降级问题之Redis用于搭建分布式缓存集群问题如何解决