FastDFS + SpringBoot + RestFul 简单的完成文件上传(简单)

一个简单的FastDFS + SpringBoot + RestFul 上传文件的案例

前言:FastDFS是一个新接触的技术,SpringBoot和RestFul在本文中就不做介绍了,阅读本文需要有SpringBoot和RestFul的基础

FastDFS

什么是 FastDFS
FastDFS 是⼀个开源的轻量级分布式⽂件系统,它解决了⼤数据量存储和负载均衡等问题,特别适合以中⼩ ⽂件(建议范围:4 KB < file_size < 500 MB)为载体的在线服务,如相册⽹站、视频⽹站等。在 UC 基于 FastDFS 开发向⽤户提供了⽹盘、社区、⼴告和应⽤下载等业务的存储服务。

FastDFS 由 C 语⾔开发,⽀持 Linux、FreeBSD 等 UNIX 系统类 Google FS,不是通⽤的⽂件系统,只能通 过专有 API 访问,⽬前提供了 C、Java 和 PHP API,为互联⽹应⽤量身定做,解决了⼤容量⽂件存储问 题,追求⾼性能和⾼扩展性,FastDFS 可以看做是基于⽂件的 Key Value Pair 存储系统,称作分布式⽂件存 储服务会更合适。

FastDFS 特性
⽂件不分块存储,上传的⽂件和 OS ⽂件系统中的⽂件⼀⼀对应 ⽀持相同内容的⽂件只保存⼀份,节约磁盘空间 下载⽂件⽀持 HTTP 协议,可以使⽤内置 Web Server,也可以和其他 Web Server 配合使⽤ ⽀持在线扩容 ⽀持主从⽂件 存储服务器上可以保存⽂件属性(meta-data)V2.0 ⽹络通信采⽤ libevent,⽀持⼤并发访问,整体性 能更好

FastDFS 相关概念
FastDFS 服务端有三个⻆角⾊:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端 (Client)。
Tracker Server:跟踪服务器,主要做调度⼯作,起负载均衡的作⽤。在内存记录集群中所有存储组和 存储服务器的状态信息,是客户端和数据服务器交互的枢纽。相⽐ GFS 中的 Master 更为精简,不记录 ⽂件索引信息,占⽤的内存量很少。 Storage Server:存储服务器(⼜称存储节点或数据服务器),⽂件和⽂件属性(Meta Data)都保存 到存储服务器上。Storage Server 直接利⽤ OS 的⽂件系统调⽤管理⽂件。 Client:客户端,作为业务请求的发起⽅,通过专有接⼝,使⽤ TCP/IP 协议与跟踪器服务器或存储节 点进⾏数据交互。FastDFS 向使⽤者提供基本⽂件访问接⼝,如 upload、download、append、delete 等,以客户端库的⽅式提供给⽤户使⽤。

上传机制

首先客户端请求 Tracker 服务获取到存储服务器的 IP 地址和端口,然后客户端根据返回的 IP 地址和端口号请求上传文件,存储服务器接收到请求后生产文件,并且将文件内容写入磁盘并返回给客户端 file_id、路径信息、文件名等信息,客户端保存相关信息上传完毕。

图示

在这里插入图片描述

项目结构

在这里插入图片描述

fastdfs包

FastDFSFile:改类是上传的工具类,封装FastDFSFile。主要包括文件的基础信息 [文件名,内容,文件的类型,作者]

代码

package com.jimmy.fastdfs;

/**
 * @Author Jimmy
 * @Date 2019/8/22 9:25 PM
 * @Desc
 *
 * 上传工具类:
 * 封装 FastDFSFile,文件基础信息包括文件名、内容、文件类型、作者等
 */

public class FastDFSFile {
    //文件名
    private String name;
    //文件内容
    private byte[] content;
    //文件类型
    private String ext;
    //作者 (上传者)
    private String author;

    public FastDFSFile() {
    }


    public FastDFSFile(String name, byte[] content, String ext, String author) {
        this.name = name;
        this.content = content;
        this.ext = ext;
        this.author = author;
    }

    public FastDFSFile(String name, byte[] content, String ext) {
        this.name = name;
        this.content = content;
        this.ext = ext;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }

    public String getExt() {
        return ext;
    }

    public void setExt(String ext) {
        this.ext = ext;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

FastDFSClient:该类客户端 提供上传文件

代码

package com.jimmy.fastdfs;

import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.core.io.ClassPathResource;


import java.io.IOException;

/**
 * @Author Jimmy
 * @Date 2019/8/22 9:29 PM
 * @Desc
 *
 * FastDFSClient:客户端 提供上传文件
 */

public class FastDFSClient {


    //TODO 1.类加载时读取配置信息,并进行初始化
    static {
        try {
            String path = new ClassPathResource("FastDFS.conf").getFile().getAbsolutePath();
            //FastDFS客户端初始化方法
            ClientGlobal.init(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //TODO 2.上传文件
    public static String[] upload(FastDFSFile file){

        //打印查看文件的信息 文件名和文件的字节长度
        System.out.println("FileName:" + file.getName() + " FileContent:" + file.getContent().length);


        //文件属性
        //NameValuePair,主要存储文件的一些基础属性,如作者信息、创建时间等
        NameValuePair[] nameValuePair = new NameValuePair[1];
        nameValuePair[0] = new NameValuePair("author",file.getAuthor());


        //上传结果
        String[] uploadResults = null;

        //存储客户端
        StorageClient storageClient = null;

        try {
            //获取客户端实例
            storageClient = getStorageClient();
            //封装最终上传结果
            uploadResults = storageClient.upload_file(file.getContent(),file.getExt(),nameValuePair);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //验证上传结果
        if (uploadResults == null && storageClient != null) {
            //这里直接打印上传文件失败 不做其他操作
            System.out.println("上传文件失败");
        }
        System.out.println("上传文件成功");
        return uploadResults;
    }


    /**
     * 首先获取 TrackerServer [追踪服务器] 信息,
     * 使用 TrackerServer 构建出每次操作的客户端实例 StorageClient
     * @return
     */
    private static StorageClient getStorageClient() throws IOException {
        //获取TrackerServer
        TrackerServer trackerServer = getTrackerServer();
        StorageClient client = new StorageClient(trackerServer, null);
        return client;
    }

    /**
     * 获取TrackerServer的方法
     * @return
     */
    private static TrackerServer getTrackerServer() throws IOException {

            TrackerClient trackerClient = new TrackerClient();
            //客户端获得追踪服务器的连接
            TrackerServer server = trackerClient.getConnection();
            return server;
    }

    /**
     * TODO 上传文件返回的URL
     * @return
     * @throws IOException
     */
    public static String getTrackerUrl() throws IOException {
        return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/";
    }
}

controller包

UploadFileController:处理文件上传的controller

代码

package com.jimmy.controller;

import com.jimmy.fastdfs.FastDFSClient;
import com.jimmy.fastdfs.FastDFSFile;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;

import java.io.IOException;
import java.io.InputStream;

/**
 * @Author Jimmy
 * @Date 2019/8/22 10:15 PM
 * @Desc 处理文件上传的controller
 */

@RestController
@RequestMapping("/fastdfs")
public class UploadFileController {

    /**
     * TODO 上传文件的接口
     * @param file
     * @return
     */

    @PostMapping("/upload")
    public ResponseEntity<String> upload(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return new ResponseEntity<>("文件为不能为空",HttpStatus.INTERNAL_SERVER_ERROR);
        }
        String path = saveFile(file);
        return new ResponseEntity<>(path,HttpStatus.CREATED);
    }



    public String saveFile(MultipartFile file) throws IOException {
        //文件信息
        String[] fileInformation = {};
        //文件的名称
        String fileName = file.getOriginalFilename();
        //通过文件的名称获取文件的类型
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);

        //储存文件内容的字节数组
        byte[] fileContent = null;

        InputStream inputStream = file.getInputStream();
        //一下操作是将文件读取到字节数组
        if (inputStream != null) {
            int length = inputStream.available();
            fileContent = new byte[length];
            inputStream.read(fileContent);
        }
        //关闭流
        inputStream.close();
        FastDFSFile fastDFSFile = new FastDFSFile(fileName, fileContent, fileType);

        fileInformation = FastDFSClient.upload(fastDFSFile);

        String path = FastDFSClient.getTrackerUrl() + fileInformation[0] + "/" + fileInformation[1];
        return path;
    }
}

UploadFile.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <script type="text/javascript" src="js/jquery.min.js"></script>
</head>
<body>

    <script>
        $(function () {
            $("#button").click(function () {

                var data = new FormData;
                var file = $("#file").prop("files");
                data.append("file",file[0]);

                $.ajax({
                    type: "POST",
                    url: "/fastdfs/upload",
                    data: data,
                    cache: false,
                    processData: false,
                    contentType: false,
                    statusCode: {
                        201: function (data) {
                            alert("上传成功!文件的路径为:"+data)
                            window.location.href = data;
                        },
                        500: function (data) {
                            console.log(data.toString())
                            alert("文件上传失败")
                        }
                    }
                });
            })
        })
    </script>

    <div>
        <form>
            <input type="file" id="file"/>
            <input type="button" id="button" value="上传"/>
        </form>
    </div>
</body>
</html>

application.properties

### 最大上传文件大小
spring.servlet.multipart.max-file-size=10MB
### 总上传的文件大小
spring.servlet.multipart.max-request-size=10MB

配置文件 FastDFS.conf

connect_timeout = 60
network_timeout = 60
charset = UTF-8
http.tracker_http_port = 追踪服务器端口号
http.anti_steal_token = no
http.secret_key = 123456

tracker_server = 服务器IP:22122

pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jimmy</groupId>
    <artifactId>springboot_fastdfs</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_fastdfs</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.csource</groupId>
            <artifactId>fastdfs-client-java</artifactId>
            <version>1.27-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
发布了30 篇原创文章 · 获赞 40 · 访问量 6511

猜你喜欢

转载自blog.csdn.net/ScholarTang/article/details/100040460