FastDFS
一、什么是FastDFS?
FastDFS是一个开源的轻量级分布式文件存储系统,可以供我们去完成文件的上传与下载。在FastDFS中由两部分组成,分别是tracker、Storage
- tracker:是专门去管理storage的,在FastDFS中所有的访问都会先经过tracker,并由tracker去找有哪些storage压力小或者比较空闲,那么tracker就会返回一个storage地址供我们去上传下载
- storage:职责就是保存上传的数据以及对数据的下载
二、使用Docker安装FastDFS
注:docker搜索镜像文件是需要联网的!!!
1、查看fastdfs都有哪些版本(搜索镜像文件)
docker search fastdfs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dPR7U7Zt-1670471640515)(4a85625ec7d7017239bdbeee890dabb2.png)]2、拉取镜像,我这里选择的是delron/fastdfs版本(其他版本也是可以的,但是建议不要拉取太新的版本)
docker pull delron/fastdfs
拉取成功后,使用指令docker image查看镜像列表,可以看到下载的fastdfs[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odeIJrP3-1670471640517)(0b451a8725390fd3b0e3c025bb11dac6.png)]
3、启动tracker
docker run -d --network=host --name tracker -v /home/fastdfs/docker/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
docker run -d --=host --name tracker -v /home/fastdfs/docker/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
–network=host:表示的是使用的网络模式为network模式
-d:表示后台启动
4、启动storage
docker run -d --network=host --name storage -e TRACKER_SERVER=ip:22122 -v /home/fastdfs/docker/fastdfs/storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage
注意:
- ER_SERVER=ip:22122。ip要改成自己当前的ip地址
- GROUP_NAME=group1。storage组名可以自己设置
5、释放8888,23000,22122端口
firewall-cmd --zone=public --add-port=8888/tcp --permanent
firewall-cmd --zone=public --add-port=23000/tcp --permanent
firewall-cmd --zone=public --add-port=22122/tcp --permanent
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8NYNcevg-1670471640518)(cecc512abf56aeeca8c6c69e8fd6b848.png)]
注意:
全部启动成功后fastdfs默认有三个端口号(放8888,23000,22122),需要在服务器中放行这三个端口号。
- 8888:默认是nginx代理的端口 delron/fastdfs这个版本包含有nginx
- 23000:storage服务端口
- 22122:tracker服务端口
6、重启防火墙
# 重启之后释放的端口才会生效
systemctl reload firewalld
7、查看已放行的端口号
firewall-cmd --list-ports
三、在springboot中应用fastDFS实现文件的上传下载删除
3.1 创建springboot工程
略~
3.2 添加fastDFS依赖
<!--分布式文件存储 fastDFS-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
<!--上传下载 间接包-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
3.3 在springboot启动类中加上以下两个注解
//加载fastDFS
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
@Import(FdfsClientConfig.class)
3.4 配置application.yml文件
#在application.yml中配置fastdfs的连接地址等信息
注意这个trackerList:如果是集群tracker的话以逗号分隔开就行
fdfs:
connect-timeout: 600
so-timeout: 1500
trackerList: 服务器tracker的ip:22122
thumb-image:
width: 150
height: 150
pool:
max-total: 200
fastdfs默认上传文件大小是1MB左右~所以需要我们根据自己项目的需要配置最大上传文件的大小、以及最大上传的数据大小(默认是MB)
# 最大上传单个文件大小:默认1M
spring.servlet.multipart.max-file-size=1024MB
# 最大置总上传的数据大小 :默认10M
spring.servlet.multipart.max-request-size=1024MB
3.5 书写Controller层代码–测试上传用例
package com.xgsm.fastdfsdemo;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
@RestController
@RequestMapping("/file")
@Api(value = "fastDFs分布式文件存储 -- 文件上传下载", description = "fastDFs分布式文件存储 -- 文件上传下载")
@CrossOrigin//跨域的意思
public class FileController{
//FastFileStorageClient 直接注入就能用 fastdsf自带的
@Resource
private FastFileStorageClient fastFileStorageClient;
//fastDFS storage存储节点路径 xxxxxx:服务器ip
private final String FASTDFSSERVERIMAGE = "http://192.168.85.129:8888/";
/**
* 文件上传
* @Async开启异步
* @return result
*/
@ApiOperation("上传")
@Async("asyncServiceExecutor")
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public HashMap<String, String> upload(@RequestPart("file") MultipartFile file) {
HashMap<String, String> result = new HashMap<>();
try {
//这里msg返回的是上传后的图片存储位置getFullPath()获取文件位置
result.put("msg", FASTDFSSERVERIMAGE + fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), null).getFullPath());
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
打开ApiPost或者Postman或Swagger-ui进行测试
返回的结果在浏览器中打开就可以看到我们上传的图片了
注意!!!!!这里很有可能会出现一个这样的问题,上传的时候,不同的文件有的时候上传成功有的时候上传失败;发生的原因大致有两种:一种是TrackerService地址配错了(但是不会出现时好时坏的情况),另一种是超时(配置fastDFS超时时间是以秒为单位,通过ClientGlabal的setG_connect_timeout(int connect_timeout)和setG_network_timeout(int network_timeout)设置超时时间是以毫秒为单位即可)。
解决措施:
1、检查TrackerService地址是否正确
2、延长超时时间
3.6 书写Controller层代码–测试删除用例
删除上传的文件,只需要将上传成功后返回的路径传递给‘删除’即可
package com.xgsm.fastdfsdemo;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
@RestController
@RequestMapping("/file")
@Api(value = "fastDFs分布式文件存储 -- 文件上传下载", description = "fastDFs分布式文件存储 -- 文件上传下载")
@CrossOrigin//跨域的意思
public class FileController{
//FastFileStorageClient 直接注入就能用 fastdsf自带的
@Resource
private FastFileStorageClient fastFileStorageClient;
/**
* 文件删除
*
* @param path
* @return
*/
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@ApiOperation("删除")
public HashMap<String, Object> delete(@RequestParam String path) {
HashMap<String, Object> result = new HashMap<>();
fastFileStorageClient.deleteFile(path);
result.put("msg", "大哥啦~~~!!,删除成功!");
return result;
}
}
使用ApiPost发送‘删除’请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KMvetDFW-1670471640521)(06dcd4c429a895699f192ba624970a29.png)]
删除成功后,再次在浏览器中访问,则会404-------删除成功
3.7 书写Controller层代码–测试下载用例
下载的时候需要根据不同的传递参数,用不同的截取方式去截取参数之后再进行赋值
package com.xgsm.fastdfsdemo;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
@RestController
@RequestMapping("/file")
@Api(value = "fastDFs分布式文件存储 -- 文件上传下载", description = "fastDFs分布式文件存储 -- 文件上传下载")
@CrossOrigin//跨域的意思
public class FileController{
//FastFileStorageClient 直接注入就能用 fastdsf自带的
@Resource
private FastFileStorageClient fastFileStorageClient;
/**
* 文件下载
*
* @param url 路径
* @return
*/
@RequestMapping(value = "/download", method = RequestMethod.GET)
@ApiOperation("下载")
public void downLoad(@RequestParam String url, HttpServletResponse response) throws IOException {
byte[] bytes = this.downloadFile(url);
/** TODO 这里只是为了整合fastdfs,所以写死了文件格式。需要在上传的时候保存文件名。下载的时候使用对应的格式 **/
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("sb.jpg", "UTF-8"));
response.setCharacterEncoding("UTF-8");
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//封装的下载方法
public byte[] downloadFile(String fileUrl) throws IOException {
// http://192.168.85.129:8888/group1/M00/00/00/wKhVgWORP16AcJceAAAUk7NNFOw361.png
// fileUrl:group1/M00/00/00/wKhVgWORP16AcJceAAAUk7NNFOw361.png
String group = fileUrl.substring(0, fileUrl.indexOf("/"));
// group需要截取的参数是:group1
String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
// path需要截取的参数是: M00/00/00/wKhVgWORQquACgpsAALwnDncol8784.jpg
DownloadByteArray downloadByteArray = new DownloadByteArray();
byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
return bytes;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8cwAe0E-1670471640523)(4df7e6563f146d3b4ac1f1822fb88634.png)]
gitee源码地址:
https://gitee.com/xgsm/springboot-fast-dfss.git