个人技术博客——在springboot中实现FASTDFS分片文件上传

042201126杨世铭 2024-12-12 18:29:31

 

这个作业属于哪个课程2401_CS_SE_FZU
这个作业要求在哪里软件工程实践总结&个人技术博客
这个作业的目标回顾和总结课程内容以及个人技术总结
其他参考文献《构建之法》

 

目录

1.技术概述

1.1学习原因

1.2技术难点

2.技术实现

2.1流程图

2.2代码实现

2.2.1环境配置(如果已经配好环境可跳过)

2.2.2java代码实现

3.难点以及解决办法


1.技术概述


FASTDFS 是一款开源的分布式文件系统,主要用于解决大规模文件的存储和访问问题,支持分片存储和负载均衡,适合图片、视频等大文件的上传与下载。通过与 Nginx 配合,可以实现隐藏文件存储的真实地址。

1.1学习原因

其实现在阿里云、腾讯等公司提供了很多更快、更好、更安全的文件服务,除了价钱不太友好,其他地方可谓是哪里都好。但自己搭一个分布式文件管理系统,也是有好处的。至少不会那么贵?而且如果是学习阶段也能学到更多底层的知识。

1.2技术难点

  • 快速部署 FASTDFS 和配置 Nginx 做反向代理。
  • 实现分片上传、分片合并和断点续传。
  • 解决分布式存储中的同步和文件访问效率问题。

2.技术实现

2.1流程图

 

2.2代码实现

2.2.1环境配置(如果已经配好环境可跳过)

磁盘目录

 

说明位置
所有安装包/usr/local/src
数据存储位置/home/dfs/
mkdir /home/dfs #创建数据存储目录
cd /usr/local/src #切换到安装目录准备下载安装包

安装libfastcommon

git clone https://github.com/happyfish100/libfastcommon.git --depth 1
cd libfastcommon/
./make.sh && ./make.sh install #编译安装
cd ../ #返回上一级目录

安装libserverframe

git clone https://github.com/happyfish100/libserverframe.git --depth 1
cd libserverframe/
./make.sh && ./make.sh install #编译安装
cd ../ #返回上一级目录

安装FastDFS

git clone https://github.com/happyfish100/fastdfs.git --depth 1
cd fastdfs/
./make.sh && ./make.sh install #编译安装
#配置文件准备
cp /usr/local/src/fastdfs/conf/http.conf /etc/fdfs/ #供nginx访问使用
cp /usr/local/src/fastdfs/conf/mime.types /etc/fdfs/ #供nginx访问使用
cd ../ #返回上一级目录

安装fastdfs-nginx-module

git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1
cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs

安装nginx

wget http://nginx.org/download/nginx-1.15.4.tar.gz #下载nginx压缩包
tar -zxvf nginx-1.15.4.tar.gz #解压
cd nginx-1.15.4/
#添加fastdfs-nginx-module模块
./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ 
make && make install #编译安装

单机部署

tracker配置

wget http://nginx.org/download/nginx-1.15.4.tar.gz #下载nginx压缩包
tar -zxvf nginx-1.15.4.tar.gz #解压
cd nginx-1.15.4/
#添加fastdfs-nginx-module模块
./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ 
make && make install #编译安装

storage配置

vim /etc/fdfs/storage.conf
#需要修改的内容如下
port=23000  # storage服务端口(默认23000,一般不修改)
base_path=/home/dfs  # 数据和日志文件存储根目录
store_path0=/home/dfs  # 第一个存储目录
tracker_server=192.168.52.1:22122  # tracker服务器IP和端口
http.server_port=8888  # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)

client测试

vim /etc/fdfs/client.conf
#需要修改的内容如下
base_path=/home/dfs
tracker_server=192.168.52.1:22122    #tracker服务器IP和端口
#保存后测试,返回ID表示成功 如:group1/M00/00/00/xx.tar.gz
fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/nginx-1.15.4.tar.gz

配置nginx访问

vim /etc/fdfs/mod_fastdfs.conf
#需要修改的内容如下
tracker_server=192.168.52.1:22122  #tracker服务器IP和端口
url_have_group_name=true
store_path0=/home/dfs
#配置nginx.config
vim /usr/local/nginx/conf/nginx.conf
#添加如下配置
server {
    listen       8888;    ## 该端口为storage.conf中的http.server_port相同
    server_name  localhost;
    location ~/group[0-9]/ {
        ngx_fastdfs_module;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
    root   html;
    }
}
#测试下载,用外部浏览器访问刚才已传过的nginx安装包,引用返回的ID
http://192.168.52.1:8888/group1/M00/00/00/wKgAQ1pysxmAaqhAAA76tz-dVgg.tar.gz
#弹出下载单机部署全部跑通

2.2.2java代码实现

导入依赖

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

分片上传文件

 //上传可以断点传续的文件
    public String uploadAppenderFile(MultipartFile file) throws Exception {
        String fileType=getFileType(file);
        String fileName=file.getOriginalFilename();
        StorePath storePath=appendFileStorageClient.uploadAppenderFile(DEFAULT_GROUP, file.getInputStream(),file.getSize(),fileType);
        return storePath.getPath();
    }

    //断点续传
    public void modifyAppenderFile(MultipartFile file,String filepath,long offset) throws Exception {
        appendFileStorageClient.modifyFile(DEFAULT_GROUP,filepath,file.getInputStream(),file.getSize(),offset);
    }

    //
    public String uploadFileBySlices(MultipartFile file, String fileMd5, Integer sliceNo, Integer totalSliceNo) throws Exception {
        if(file == null || sliceNo == null || totalSliceNo == null){
            throw new ConditionException("参数异常!");
        }
        String pathKey = PATH_KEY + fileMd5;
        String uploadedSizeKey = UPLOADED_SIZE_KEY + fileMd5;
        //已经上传的分片数
        String uploadedNoKey = UPLOADED_NO_KEY + fileMd5;
        //已经上传的分片大小
        String uploadedSizeStr = redisTemplate.opsForValue().get(uploadedSizeKey);
        Long uploadedSize = 0L;
        if(!StringUtil.isNullOrEmpty(uploadedSizeStr)){
            uploadedSize = Long.valueOf(uploadedSizeStr);
        }
        if(sliceNo == 1){ //上传的是第一个分片
            String path = this.uploadAppenderFile(file);
            if(StringUtil.isNullOrEmpty(path)){
                throw new ConditionException("上传失败!");
            }
            redisTemplate.opsForValue().set(pathKey, path);
            redisTemplate.opsForValue().set(uploadedNoKey, "1");
        }else{
            String filePath = redisTemplate.opsForValue().get(pathKey);
            if(StringUtil.isNullOrEmpty(filePath)){
                throw new ConditionException("上传失败!");
            }
            this.modifyAppenderFile(file, filePath, uploadedSize);
            redisTemplate.opsForValue().increment(uploadedNoKey);
        }
        // 修改历史上传分片文件大小
        uploadedSize  += file.getSize();
        redisTemplate.opsForValue().set(uploadedSizeKey, String.valueOf(uploadedSize));
        //如果所有分片全部上传完毕,则清空redis里面相关的key和value
        String uploadedNoStr = redisTemplate.opsForValue().get(uploadedNoKey);
        Integer uploadedNo = Integer.valueOf(uploadedNoStr);
        String resultPath = "";
        if(uploadedNo.equals(totalSliceNo)){
            resultPath = redisTemplate.opsForValue().get(pathKey);
            List<String> keyList = Arrays.asList(uploadedNoKey, pathKey, uploadedSizeKey);
            redisTemplate.delete(keyList);
        }
        return resultPath;
    }

3.难点以及解决办法

难点 1:Nginx 配置不生效

  • 问题: 配置完 Nginx 后无法访问上传的文件,提示 404 错误。
  • 解决: 检查 /etc/fdfs/mod_fastdfs.conf 中的 store_pathtracker_server 是否配置正确,同时确保 Nginx 的工作目录与 FASTDFS 存储目录一致。

难点 2:分片上传中断后无法续传

  • 问题: 网络问题导致部分分片未上传成功,文件无法合并。
  • 解决: 在上传分片时记录每个分片的上传状态,断点续传时只上传失败的分片。

 

 

...全文
103 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

109

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 言1837
  • 防震水泥
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧