FastDFS之文件上传
1、FastDFS简介
FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过Tracker server 调度最终由 Storage server 完成文件上传和下载。Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。可以将storage称为存储服务器
2、文件上传流程
客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名
组名:文件上传后所在的 storage 组名称,在文件上传成功后有storage 服务器返回,需要客户端自行保存。
虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。
数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
3、搭建文件存储微服务
创建文件管理微服务 service_file,该工程主要用于实现文件上传以及文件删除等功能。
3.1 修改pom.xml,引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs‐client‐java</artifactId>
<version>1.27.0.0</version>
</dependency>
</dependencies>
3.2 在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf
# 连接超时时间,单位为秒。
connect_timeout=60
# 通信超时时间,单位为秒
network_timeout=60
# 字符集
charset=utf-8
# tracker的http端口:浏览器访问
http.tracker_http_port=8080
# Tracker服务器与外界通信的IP和端口:Java程序访问
tracker_server=192.168.33.133:22122
3.3 在resources文件夹下创建application.yml
server:
port: 18082
spring:
application:
name: file
servlet:
multipart:
max‐file‐size: 10MB
max‐request‐size: 10MB
main:
allow‐bean‐definition‐overriding: true # 当遇到同样名字的时候,是否允许覆盖注册
eureka:
client:
service‐url:
defaultZone: http://127.0.0.1:7001/eureka
instance:
prefer‐ip‐address: true
- max-file-size是单个文件大小
- max-request-size是设置总上传的数据大小
3.4 创建启动类
@SpringBootApplication
@EnableEurekaClient
public class FileApplication {
public static void main(String[] args) {
SpringApplication.run(FileApplication.class);
}
}
4、文件上传示例代码
4.1 文件信息封装
文件上传一般都有文件的名字、文件的内容、文件的扩展名、文件的md5值、文件的作者等相关属性,我们可以创建一个对象封装这些属性。
package com.changgou.file;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FastDFSFile {
// 文件名字
private String name;
// 文件内容
private byte[] content;
// 文件扩展名
private String ext;
// 文件MD5摘要值
private String md5;
// 文件创建作者
private String author;
public FastDFSFile(String name, byte[] content, String ext, String
height,String width, String author) {
this.name = name;
this.content = content;
this.ext = ext;
this.author = author;
}
public FastDFSFile(String name, byte[] content, String ext) {
super();
this.name = name;
this.content = content;
this.ext = ext;
}
}
4.2、文件操作工具类
package com.changgou.utils;
import com.changgou.file.FastDFSFile;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
public class FastDFSUtils {
static {
try{
// 获得配置文件路径
String file = new ClassPathResource("fsdf_client.conf").getPath();
// 加载tracker配置信息
ClientGlobal.init(file);
} catch(Exception e){
e.printStackTrace();
}
}
/**
* 文件上传方法
* @param file
* @return
*/
public static String[] upload(FastDFSFile file) {
// 获取文件的作者
NameValuePair[] meta_list = new NameValuePair[1];
meta_list[0] = new NameValuePair("author", file.getAuthor());
// 接收返回数据
String[] uploadResults = null;
StorageClient storageClient = null;
try {
// 创建StorageClient客户端对象
storageClient = getTrackerClient();
/**
* 1)文件字节数组
* 2)文件扩展名
* 3)文件作者
*/
uploadResults = storageClient.upload_file(file.getContent(),file.getExt(),meta_list);
} catch (Exception e){
log.error("Exception when uploadind the file:" +
file.getName(), e);
}
if (uploadResults == null && storageClient!=null) {
log.error("upload file fail, error code:" +
storageClient.getErrorCode());
}
// 获取组名
String groupName = uploadResults[0];
// 获取文件存储路径
String remoteFileName = uploadResults[1];
return uploadResults;
}
/**
* * 获取Storage客户端
*/
private static StorageClient getTrackerClient() throws IOException {
TrackerServer trackerServer = getTrackerServer();
StorageClient storageClient = new StorageClient(trackerServer,
null);
return storageClient;
}
/*
**
* 获取Tracker服务器
*/
private static TrackerServer getTrackerServer() throws IOException {
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
}
4.3、文件上传控制器
@RestController
@CrossOrigin
public class FileController {
@PostMapping("/upload")
public Result uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
// 创建FastDFSFile对象:封装文件数据
FastDFSFile fastDFSFile = new FastDFSFile(
file.getOriginalFilename(),
file.getBytes(),
StringUtils.getFilenameExtension(file.getOriginalFilename()));
// 调用工具类方法执行上传
String[] uploadResults = FastDFSUtils.upload(fastDFSFile);
// 获取组名
String groupName = uploadResults[0];
// 获取文件存储路径
String remoteFileName = uploadResults[1];
// 拼接访问地址
String url = "http://192.168.33.133:8080/"+groupName+"/"+remoteFileName;
return new Result(true, StatusCode.OK, "上传成功",url);
}
}