10分钟带你学会FastDFS分布式文件管理系统,就是这么快!

优采云 发布时间: 2022-09-17 04:33

  10分钟带你学会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的魅力所在。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线