总体思路:
1、安装fastdfs
2、通过使用fastdfs-client实现文件上传、下载
3、spring boot整合实现文件上传、下载
主打的就是spring boot整合实现文件上传、下载对于fastdfs不是很了解
FastDFS 是一个开源的高性能分布式文件系统,可以实现文件的存储、上传、下载等基本操作,适合于以文件为核心的在线服务,如图片分享、音视频网站、博客网站等。它由两部分组成:
跟踪器(Tracker Server):用于管理所有的 storage server,并提供文件上传和下载的负载均衡。
存储节点(Storage Server):实际保存文件的服务器。
FastDFS 的特点包括:
高可靠性:支持主备模式,实现了双机热备和多机冗余。
高扩展性:支持添加和删除 storage server,即可在不停服的情况下动态扩展存储容量和处理能力。
高性能:通过反复优化和精简代码,实现了快速响应请求和数据的高效传输。
易于集成:提供多语言 API 和丰富的客户端工具,可以方便地与其他 Web 应用程序一起使用。
FastDFS 的原理是将大文件切割成小文件块并分配到不同的 Storage Server 上进行存储,因此它既能够实现高效的大文件传输,又能避免单个节点存储过大文件而导致存储性能衰减的问题。同时,FastDFS 采用固定大小的文件切片策略,能够使存储节点间的负载均衡更加平衡。
FastDFS 的部署相对简单,它是一个轻量级且易于安装和维护的开源项目,可以为大型 Web 应用程序提供高效、稳定、可靠的基础文件服务。
一、使用docker安装fastdfs
1、拉取镜像文件
docker pull delron/fastdfs # 这个里面集成了nginx,我们就不需要在自己安装nginx了更加便捷
2、创建Tracker Server
用于管理所有的 storage server,并提供文件上传和下载的负载均衡。
在此之前我先创建了几个文件夹来准备进行数据卷的挂载
tracker服务默认的端口为22122
docker run -d --name tracker --network=host -v /usr/local/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
3、创建Storage Server
ip要写虚拟机的ip或服务器的ip,不能使用localhost和127.0.0.1,在客户端里面测试没问题,我在spring boot整合的时候连不上给我提示拒绝连接了
docker run -d --name storage --network=host -e TRACKER_SERVER=ip:22122 -v /usr/local/fastdfs/storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage
4、检查配置以及修改
现在正常来说就已经可以使用fastdfs-client测试了,但可能后续会修改相关的配置,需要看一下,哪点是需要注意的
进入storage服务查看nginx访问端口。
这个镜像中storage自带了nginx的,更加便于用户访问
docker exec -it storage bash # 进入storage
cat /etc/fdfs/storage.conf # 查看storage配置
cat /usr/local/nginx/conf/nginx.conf # 查看nginx的配置
端口一致即可
5、测试上传和下载
通过工具将文件上传到之前挂载的数据卷的宿主机的目录里面去(放到storage文件夹)
然后通过fastdfs-client上传
和宿主机映射的文件目录为/var/fastdfs
上传命令
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf xxx.png
/usr/bin/fdfs_upload_file 是 FastDFS 客户端工具,用于从命令行上传文件到 FastDFS 服务器。
/etc/fdfs/client.conf 则是 FastDFS 客户端的配置文件,包含了客户端操作时需要使用的基本参数(如 Tracker Server 的 IP 地址和端口号、Storage Server 的组名等)。
通过在 /usr/bin/fdfs_upload_file 后面加上 /etc/fdfs/client.conf 参数来指定客户端工具使用的配置文件。使用该工具可以方便地上传文件到 FastDFS 中,通过 File ID 来访问这些文件。
通过ip+端口+返回的这个字符串就可以直接访问了(需要注意的是,在虚拟机或云服务器上,这些端口需要开放,同时云服务器还需要开放对应的安全组才能访问)
效果如下:
二、spring boot整合使用fastdfs
1、引入依赖并配置fastdfs的配置
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.27.2</version>
</dependency>
2、常用api接口解释
uploadFile(String groupName, InputStream inputStream, long fileSize, String fileExtName)
- 参数:
-
groupName
:上传文件所属的组名。 -
inputStream
:输入流对象,指向要上传的文件内容。 -
fileSize
:上传文件的大小,单位为字节。 -
fileExtName
:上传文件的扩展名。
- 返回值:一个
StorePath
对象,其中封装文件的路径和 store 节点的地址。
uploadSlaveFile(String groupName, String masterFilename, InputStream inputStream, long fileSize, String prefixName, String fileExtName)
- 参数:
-
groupName
:文件上传到的组名。 -
masterFilename
:主文件的名称。 -
inputStream
:从文件的输入流对象。 -
fileSize
:上传从文件的大小,单位为字节。 -
prefixName
: 从文件名前缀 -
fileExtName
:从文件的扩展名
- 返回值:一个
StorePath
对象,表示成功上传后从文件存储的路径信息。
getMetadata(String groupName, String path)
- 参数:
-
groupName
:文件所属的分组名。 -
path
:文件的在 FastDFS 存储中真实的路径。
- 返回值:Set 集合,其中包含多组 metadata 信息。每一条 metadata 是 k-v 形式的键值对。如果没有找到对应的 metadata 信息,则返回一个空的集合。
overwriteMetadata(String groupName, String path, Set<MetaData> metaDataSet)
- 参数:
-
groupName
:文件所属的分组名。 -
path
:文件在 FastDFS 存储中真实的路径。 -
metaDataSet
:要覆盖的新的 metadata 集合。
- 返回值:无
mergeMetadata(String groupName, String path, Set<MetaData> metaDataSet)
- 参数:
-
groupName
:文件所属的分组名。 -
path
:文件在 FastDFS 存储中真实的路径。 -
metaDataSet
:待合并的metadata集合。
- 返回值:无
queryFileInfo(String groupName, String path)
- 参数:
-
groupName
:文件所属的组名。 -
path
:文件在 FastDFS 存储中真实的路径。
- 返回值:一个
FileInfo
对象,包含了文件的元数据信息。
deleteFile(String groupName, String path)
- 参数:
-
groupName
:文件所属的组名。 -
path
:文件在 FastDFS 存储中真实的路径。
- 返回值:无
downloadFile(String groupName, String path, DownloadCallback<T> callback)
- 参数:
-
groupName
:文件所属的组名。 -
path
:文件在 FastDFS 存储中真实的路径。 -
callback
:下载回调接口对象。
- 返回值:一个泛型值对象 T,表示经过回调方法处理后的结果。
downloadFile(String groupName, String path, long fileOffset, long fileSize, DownloadCallback<T> callback)
- 参数:
-
groupName
:文件所属的组名。 -
path
:文件在 FastDFS 存储中真实的路径。 -
fileOffset
:文件偏移量,从哪个地方开始下载。 -
fileSize
:要下载的文件大小。 -
callback
:下载回调接口对象。
- 返回值:一个泛型值对象 T,表示经过回调方法处理后的结果。
总的来说,这些参数都是用于控制上传、下载、删除等操作的,不同的方法有不同的参数需求,并根据不同的需求执行相应的命令,返回相应的结果。同时,在上传和下载等操作时需要将文件指针从输入流的初始位置移动到目标位置,以便进行特定的操作。
3、测试
yml:
fdfs:
# 超时时间
connect_timeout: 5000
# 读取时间
so_timeout: 30000
# 服务地址列表
tracker-list: 192.168.19.129:22122
# 解决限制文件大小
spring:
servlet:
multipart:
max-request-size: 1TB
max-file-size: 1TB
工具类
package com.example.util;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @Classname FastdfsUtil
* @Description TODO
* @Version 1.0.0
* @Date 2023/4/5 15:14
* @Created by wlh12
*/
@Component
public class FastdfsUtil {
@Autowired
private FastFileStorageClient storageClient;
/**
* 上传
* @param file
* @return
*/
public String upload(MultipartFile file){
// 获取文件名
String filename = file.getOriginalFilename();
// 得到文件扩展名
String extName = filename.substring(filename.lastIndexOf(".") + 1);
StorePath storePath = null;
try {
// 上传
storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), extName, null);
// 这个getFullPath是fastdfs返回的id,可通过这个实现图片浏览、视频播放、文件下载等操作
return storePath.getFullPath();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
测试接口类
package com.example.controller;
import com.example.util.FastdfsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* @Classname TestController
* @Description TODO
* @Version 1.0.0
* @Date 2023/4/5 16:23
* @Created by wlh12
*/
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private FastdfsUtil fastdfsUtil;
@PostMapping("/add")
public String add(MultipartFile file){
return fastdfsUtil.upload(file);
}
}
测试结果:
直接通过这个url就能访问了。
总结: fastdfs基本使用(我项目中的开发使用足够了)就差不多了,视频和图片的展示就可以通过ip+端口+fastid就能实现了,不需要我们在写端口,下载操作我们后端需要写二进制流的形式写回客户端下载的。
例如下面:
下载的方法
/**
* 下载文件(写二进制流)
* @param path
* @return
*/
public ResponseEntity<byte[]> download(String path){
StorePath storePath = StorePath.parseFromUrl(path);
String substring = path.substring(path.lastIndexOf("."));
byte[] data = storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());
HttpHeaders httpHeaders = new HttpHeaders();
// 设置下载响应类型以及文件名
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentDispositionFormData("attachment","file"+substring );
return new ResponseEntity<>(data,httpHeaders, HttpStatus.OK);
}
接口层
@GetMapping("/download")
public ResponseEntity<byte[]> download(){
return fastdfsUtil.download("group1/M00/00/00/wKgTgWQtOVSAMbHmAAAA5xq6gXc561.txt");
}
左下角已经有了要下载的文件了,视频也是一样的,修改为我们的视频的路径测试
其他的就是继续扩展了,不多记录了 over!收工!