10分钟带你学会FastDFS分布式文件管理系统,就是这么快!
优采云 发布时间: 2022-09-17 04:3310分钟带你学会FastDFS分布式文件管理系统,就是这么快!
一. 前言
最近有很多小伙伴问健哥,*敏*感*词*的文件存储该怎么做? 这个感觉很难实现呢。其实这个需求,并没有大家想的那么难以实现。今天健哥就带着各位,用10分钟的时间来搞定这个需求。不信?那你就跟着健哥一步步来,10分钟绝对带你学会。
二. 浅析FastDFS分布式文件系统
FastDFS是一个开源的轻量级分布式文件系统,它特别适合海量的文件存储,具有文件上传、下载、文件同步和删除等功能。还可以存储各种类型文件,例如文本文件、声音文件、视频文件、图片文件等,可以用来做相册网站,还可以在电商网站中保存商品图片,在贴吧网站保存文章中的插图等。
FastDFS特点:
不要惊讶,它就是这么强大!!!
三. FastDFS执行流程和原理
接下来健哥就给大家解读FastDFS流程图中展示的执行流程和原理:
四. FastDFS安装部署
健哥在这里使用Docker容器化来搭建FastDFS。
4.1拉取镜像
docker pull morunchang/fastdfs
4.2运行tracker
创建FastDFS管理端tracker容器。
docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
4.3运行storage
创建FastDFS存储端storage容器。
docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
4.4修改nginx的配置
进入storage的容器内部,修改nginx.conf。
# 进入到storage容器内部<br />docker exec -it storage /bin/bash
进入到容器内部后。
#1. 通过命令来查询Nginx的安装位置:<br />root@iZ8vb6w2xyjemtqcxtmaj4Z:/# whereis nginx<br />#显示如下:<br />nginx: /etc/nginx<br /><br />#2. 查看当前Nginx的进程<br />root@iZ8vb6w2xyjemtqcxtmaj4Z:/# ps aux | grep nginx<br />#显示如下:<br />root 16 0.0 0.0 32480 1480 ? Ss 13:18 0:00 nginx: master process /etc/nginx/sbin/nginx<br />nobody 100 0.0 0.0 33036 2116 ? S 14:15 0:00 nginx: worker process<br />root 118 0.0 0.0 11272 728 pts/1 S+ 14:54 0:00 grep --color=auto nginx
在storage存储端容器的nginx中添加以下内容:
#3. 修改Nginx的配置文件<br />vi /etc/nginx/conf/nginx.conf<br /><br />#4. 修改Nginx配置内容<br /> server {<br /> listen 80;<br /> server_name localhost;<br /> <br /> location ~ /M00 {<br /> # storage 实际存储图片的位置<br /> root /data/fast_data/data;<br /> ngx_fastdfs_module;<br /> }<br />}<br /><br />#5. 进入到Nginx sbin目录从新加载Nginx配置文件<br />cd /etc/nginx/sbin<br /><br />#6. 重新加载配置文件, 让nginx配置生效<br />./nginx -s reload
修改后:
storage存储的位置/data/fast_data/data。
4.5设置开机启动容器
docker update --restart=always tracker<br />docker update --restart=always storage
五. 代码实现
5.1创建文件管理微服务
创建文件管理微服务fastdfsDemo,该工程主要用于实现文件上传以及文件删除等功能。创建微服务时,项目为Maven项目,不要选择骨架。
5.2修改pom.xml引入依赖
<br /><br /> org.springframework.boot<br /> spring-boot-starter-parent<br /> 2.1.5.RELEASE<br /><br /><br /><br /> <br /> UTF-8<br /> UTF-8<br /><br /> <br /> 1.8<br /> 1.8<br /><br /> <br /> 2.1.5.RELEASE<br /> 1.27.0.0<br /><br /><br /><br /> <br /> org.springframework.boot<br /> spring-boot-starter-web<br /> ${spring.boot.version}<br /> <br /> <br /> net.oschina.zcx7878<br /> fastdfs-client-java<br /> ${fastdfs.client.version}<br /> <br />
5.3创建fasfDFS的配置文件
在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf。
connect_timeout = 60<br />network_timeout = 60<br />charset = UTF-8<br />http.tracker_http_port = 80<br />tracker_server = 192.168.200.128:22122
5.4创建微服务配置文件
在resources文件夹下创建application.yml。
spring:<br /> servlet:<br /> multipart:<br /> max-file-size: 10MB<br /> max-request-size: 10MB<br /> application:<br /> name: fastdfs-demo<br />server:<br /> port: 9001
max-file-size是单个文件大小,max-request-size是设置总上传的数据大小。
创建启动类
创建com.qianfeng包,创建启动类FastDFSApplication。
package com.qianfeng;<br /><br />import org.springframework.boot.SpringApplication;<br />import org.springframework.boot.autoconfigure.SpringBootApplication;<br /><br />/**<br /> * 项目启动类<br /> * @Author 千锋健哥<br /> */<br />@SpringBootApplication<br />public class FastDFSApplication {<br /><br /> public static void main(String[] args) {<br /> SpringApplication.run(FastDFSApplication.class, args);<br /> }<br />}
5.5 文件上传
5.5.1 文件信息封装
文件上传一般都有文件的名字、文件的内容、文件的扩展名、文件的md5值、文件的作者等相关属性,我们可以创建一个对象封装这些属性。我们先创建com.qianfeng.pojo.FastDFSFile文件,代码如下:
package com.qianfeng.pojo;<br /><br />/**<br /> * 自定义封装, 文件实体类<br /> * @Author 千锋健哥<br /> */<br />public class FastDFSFile {<br /><br /> //文件名字<br /> private String name;<br /> //文件内容<br /> private byte[] content;<br /> //文件扩展名<br /> private String ext;<br /> //文件MD5摘要值<br /> private String md5;<br /> //文件创建作者<br /> private String author;<br /><br /> public FastDFSFile(String name, byte[] content, String ext, String height, String width, String author) {<br /> super();<br /> this.name = name;<br /> this.content = content;<br /> this.ext = ext;<br /> this.author = author;<br /> }<br /><br /> public FastDFSFile(String name, byte[] content, String ext) {<br /> super();<br /> this.name = name;<br /> this.content = content;<br /> this.ext = ext;<br /> }<br /><br /> // getter and setter ...<br />}
5.5.2 文件操作
创建FastDFSClient类,存放在com.qianfeng.util下,在该类中实现FastDFS信息获取以及文件的相关操作,代码如下:
package com.qianfeng.util;<br /><br />import com.qianfeng.pojo.FastDFSFile;<br />import org.csource.common.NameValuePair;<br />import org.csource.fastdfs.*;<br />import org.slf4j.LoggerFactory;<br />import org.springframework.core.io.ClassPathResource;<br /><br />import java.io.ByteArrayInputStream;<br />import java.io.IOException;<br />import java.io.InputStream;<br /><br />/**<br /> * 上传下载等文件操作工具类<br /> * @Author 千锋健哥<br /> */<br />public class FastDFSClient {<br /><br /> private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);<br /><br /> /***<br /> * 初始化加载FastDFS的TrackerServer配置<br /> */<br /> static {<br /> try {<br /> String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();<br /> ClientGlobal.init(filePath);<br /> } catch (Exception e) {<br /> logger.error("FastDFS Client Init Fail!",e);<br /> }<br /> }<br /><br /> /***<br /> * 文件上传<br /> * @param file<br /> * @return<br /> */<br /> public static String[] upload(FastDFSFile file) {<br /> //获取文件的作者<br /> NameValuePair[] meta_list = new NameValuePair[1];<br /> meta_list[0] = new NameValuePair("author", file.getAuthor());<br /><br /> //接收返回数据<br /> String[] uploadResults = null;<br /> StorageClient storageClient=null;<br /> try {<br /> //创建StorageClient客户端对象<br /> storageClient = getTrackerClient();<br /><br /> /***<br /> * 文件上传<br /> * 1)文件字节数组<br /> * 2)文件扩展名<br /> * 3)文件作者<br /> */<br /> uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);<br /> } catch (Exception e) {<br /> logger.error("Exception when uploadind the file:" + file.getName(), e);<br /> }<br /><br /> if (uploadResults == null && storageClient!=null) {<br /> logger.error("upload file fail, error code:" + storageClient.getErrorCode());<br /> }<br /> //获取组名<br /> String groupName = uploadResults[0];<br /> //获取文件存储路径<br /> String remoteFileName = uploadResults[1];<br /> return uploadResults;<br /> }<br /><br /> /***<br /> * 获取文件信息<br /> * @param groupName:组名<br /> * @param remoteFileName:文件存储完整名<br /> * @return<br /> */<br /> public static FileInfo getFile(String groupName, String remoteFileName) {<br /> try {<br /> StorageClient storageClient = getTrackerClient();<br /> return storageClient.get_file_info(groupName, remoteFileName);<br /> } catch (Exception e) {<br /> logger.error("Exception: Get File from Fast DFS failed", e);<br /> }<br /> return null;<br /> }<br /><br /> /***<br /> * 文件下载<br /> * @param groupName<br /> * @param remoteFileName<br /> * @return<br /> */<br /> public static InputStream downFile(String groupName, String remoteFileName) {<br /> try {<br /> //创建StorageClient<br /> StorageClient storageClient = getTrackerClient();<br /><br /> //下载文件<br /> byte[] fileByte = storageClient.download_file(groupName, remoteFileName);<br /> InputStream ins = new ByteArrayInputStream(fileByte);<br /> return ins;<br /> } catch (Exception e) {<br /> logger.error("Exception: Get File from Fast DFS failed", e);<br /> }<br /> return null;<br /> }<br /><br /> /***<br /> * 文件删除<br /> * @param groupName<br /> * @param remoteFileName<br /> * @throws Exception<br /> */<br /> public static void deleteFile(String groupName, String remoteFileName)<br /> throws Exception {<br /> //创建StorageClient<br /> StorageClient storageClient = getTrackerClient();<br /><br /> //删除文件<br /> int i = storageClient.delete_file(groupName, remoteFileName);<br /> }<br /><br /> /***<br /> * 获取Storage组<br /> * @param groupName<br /> * @return<br /> * @throws IOException<br /> */<br /> public static StorageServer[] getStoreStorages(String groupName)<br /> throws IOException {<br /> //创建TrackerClient<br /> TrackerClient trackerClient = new TrackerClient();<br /> //获取TrackerServer<br /> TrackerServer trackerServer = trackerClient.getConnection();<br /> //获取Storage组<br /> return trackerClient.getStoreStorages(trackerServer, groupName);<br /> }<br /><br /> /***<br /> * 获取Storage信息,IP和端口<br /> * @param groupName<br /> * @param remoteFileName<br /> * @return<br /> * @throws IOException<br /> */<br /> public static ServerInfo[] getFetchStorages(String groupName,<br /> String remoteFileName) throws IOException {<br /> TrackerClient trackerClient = new TrackerClient();<br /> TrackerServer trackerServer = trackerClient.getConnection();<br /> return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);<br /> }<br /><br /> /***<br /> * 获取Tracker服务地址<br /> * @return<br /> * @throws IOException<br /> */<br /> public static String getTrackerUrl() throws IOException {<br /> return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ ClientGlobal.getG_tracker_http_port()+"/";<br /> }<br /><br /> /***<br /> * 获取Storage客户端<br /> * @return<br /> * @throws IOException<br /> */<br /> private static StorageClient getTrackerClient() throws IOException {<br /> TrackerServer trackerServer = getTrackerServer();<br /> StorageClient storageClient = new StorageClient(trackerServer, null);<br /> return storageClient;<br /> }<br /><br /> /***<br /> * 获取Tracker<br /> * @return<br /> * @throws IOException<br /> */<br /> private static TrackerServer getTrackerServer() throws IOException {<br /> TrackerClient trackerClient = new TrackerClient();<br /> TrackerServer trackerServer = trackerClient.getConnection();<br /> return trackerServer;<br /> }<br />}
5.5.3 文件上传
创建一个FileController,在该控制器中实现文件上传操作,代码如下:
package com.qianfeng.controller;<br /><br />import com.qianfeng.pojo.FastDFSFile;<br />import com.qianfeng.util.FastDFSClient;<br />import org.springframework.web.bind.annotation.*;<br />import org.springframework.web.multipart.MultipartFile;<br /><br />import java.io.IOException;<br /><br />/**<br /> * 文件操作controller接口<br /> * @Author 千锋健哥<br /> */<br />@RestController<br />@CrossOrigin<br />@RequestMapping("/file")<br />public class FileController {<br /><br /> /**<br /> * 上传接口<br /> * @param file 接收文件参数, 参数名必须叫做file<br /> * @Author 千锋健哥<br /> */<br /> @PostMapping("/upload")<br /> public String upload(@RequestParam("file") MultipartFile file) {<br /> String path ="";<br /> try {<br /> path=saveFile(file);<br /> System.out.println(path);<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> }<br /> return path;<br /> }<br /><br /> /**<br /> * 上传文件到FastDFS分布式文件系统<br /> * @param multipartFile<br /> * @Author 千锋健哥<br /> */<br /> public String saveFile(MultipartFile multipartFile) throws IOException {<br /> //1. 获取文件名<br /> String fileName = multipartFile.getOriginalFilename();<br /> //2. 获取文件内容<br /> byte[] content = multipartFile.getBytes();<br /> //3. 获取文件扩展名<br /> String ext = "";<br /> if (fileName != null && !"".equals(fileName)) {<br /> ext = fileName.substring(fileName.lastIndexOf("."));<br /> }<br /> //4. 创建文件实体类对象<br /> FastDFSFile fastDFSFile = new FastDFSFile(fileName, content, ext);<br /> //5. 上传<br /> String[] uploadResults = FastDFSClient.upload(fastDFSFile);<br /> //6. 拼接上传后的文件的完整路径和名字, uploadResults[0]为组名, uploadResults[1]为文件名称和路径<br /> String path = FastDFSClient.getTrackerUrl() + uploadResults[0] + "/" + uploadResults[1];<br /> //7. 返回<br /> return path;<br /> }<br />}
5.4 Postman测试文件上传
测试步骤:
选择post请求方式,输入请求地址
:9001/file/upload
填写Headers
Key:Content-Type<br />Value:multipart/form-data
填写body。选择form-data 然后选择文件file 点击添加文件,最后发送即可。
postman填写信息填写如下步骤所示。
注意Headers请求头中内容
注意body请求体中内容:
上传结果后,就可以通过浏览器访问显示如下,这*敏*感*词*姐需要吗?
六. 结语
至此,各位小伙伴是否都已经跟着健哥学会了FastDFS的使用了呢?
现在挺多企业都是购买阿里云或者华为云等云服务器,然后在这些云服务器上再手动部署FastDFS,这样比直接购买使用阿里的OSS对象存储服务更节省经费,这也就是FastDFS的魅力所在。