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
称为存储服务器。
![](https://i-blog.csdnimg.cn/blog_migrate/5ccad35539f8569ad4acddd4239f76aa.png)
上传流程:
用docker创建FastDFS
拉取镜像
docker pull morunchang/fastdfs
运行tracker
docker run ‐d ‐‐name tracker ‐‐net=host morunchang/fastdfs sh tracker.sh
运行
storage
docker run ‐d ‐‐name storage ‐‐net=host ‐e TRACKER_IP=<your tracker server address>:22122 ‐e GROUP_NAME=<group name> morunchang/fastdfs sh storage.sh
修改
nginx
的配置:
1进入
storage
的容器内部,修改
nginx.conf
docker exec ‐it storage /bin/bash
2进入后修改文件
vi /data/nginx/conf/nginx.conf
添加以下内容
location /group1/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http‐cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group1; expires 30d;
}
退出容器
exit
重启
storage
容器
docker restart storage
文件存储微服务
(
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>
<dependency>
<groupId>com.changgou</groupId>
<artifactId>changgou_common</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency> </dependencies>
(
2
)在
resources
文件夹下创建
fasfDFS
的配置文件
fdfs_client.conf
connect_timeout = 60 #连接超时时间,单位为秒。
network_timeout = 60 #通信超时时间,单位为秒。发送或接收数据时。假设在超时时间后 还不能发送或接收数据,则本次网络通信失败
charset = UTF‐8 #字符集
http.tracker_http_port = 8080 #.tracker的http端口
tracker_server = 192.168.200.128:22122 # tracker服务器IP和端口设置
(
3
)在
resources
文件夹下创建
application.yml
spring: servlet: multipart: max‐file‐size: 10MB max‐request‐size: 10MB server: port: 9008 eureka: client: service‐url: defaultZone: http://127.0.0.1:6868/eureka instance: prefer‐ip‐address: true feign: hystrix: enabled: true
(
4
)创建
com.changgou.file
包,创建启动类
FileApplication
@SpringBootApplication @EnableEurekaClient public class FileApplication { public static void main(String[] args) { SpringApplication.run(FileApplication.class); } }
(5)创建com.changgou.file.pojo.FastDFSFile
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) { super(); 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; }// getter and setter ... }
(6)
创建
FastDFSClient
类
,
放在
com.changgou.file.util
下在该类中实现
FastDFS
信息获取以及
文件的相关操作,
代码如下:
public class FastDFSClient {
private static org.slf4j.Logger logger =
LoggerFactory.getLogger(FastDFSClient.class);
/***
* 初始化加载FastDFS的TrackerServer配置
*/
static {
try {
String filePath = new
ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
ClientGlobal.init(filePath);
} catch (Exception e) {
logger.error("FastDFS Client Init Fail!",e);
}
}
/***
* 文件上传
* @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)文件作者
*/北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
*/
uploadResults = storageClient.upload_file(file.getContent(),
file.getExt(), meta_list);
} catch (Exception e) {
logger.error("Exception when uploadind the file:" +
file.getName(), e);
}
if (uploadResults == null && storageClient!=null) {
logger.error("upload file fail, error code:" +
storageClient.getErrorCode());
}
//获取组名
String groupName = uploadResults[0];
//获取文件存储路径
String remoteFileName = uploadResults[1];
return uploadResults;
}
/***
* 获取文件信息
* @param groupName:组名
* @param remoteFileName:文件存储完整名
* @return
*/
public static FileInfo getFile(String groupName, String
remoteFileName) {
try {
StorageClient storageClient = getTrackerClient();
return storageClient.get_file_info(groupName,
remoteFileName);
} catch (Exception e) {
logger.error("Exception: Get File from Fast DFS failed", e);
}
return null;
}
/***
* 文件下载
* @param groupName
* @param remoteFileName
* @return北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
* @return
*/
public static InputStream downFile(String groupName, String
remoteFileName) {
try {
//创建StorageClient
StorageClient storageClient = getTrackerClient();
//下载文件
byte[] fileByte = storageClient.download_file(groupName,
remoteFileName);
InputStream ins = new ByteArrayInputStream(fileByte);
return ins;
} catch (Exception e) {
logger.error("Exception: Get File from Fast DFS failed", e);
}
return null;
}
/***
* 文件删除
* @param groupName
* @param remoteFileName
* @throws Exception
*/
public static void deleteFile(String groupName, String
remoteFileName)
throws Exception {
//创建StorageClient
StorageClient storageClient = getTrackerClient();
//删除文件
int i = storageClient.delete_file(groupName, remoteFileName);
}
/***
* 获取Storage组
* @param groupName
* @return
* @throws IOException
*/
public static StorageServer[] getStoreStorages(String groupName)北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
public static StorageServer[] getStoreStorages(String groupName)
throws IOException {
//创建TrackerClient
TrackerClient trackerClient = new TrackerClient();
//获取TrackerServer
TrackerServer trackerServer = trackerClient.getConnection();
//获取Storage组
return trackerClient.getStoreStorages(trackerServer, groupName);
}
/***
* 获取Storage信息,IP和端口
* @param groupName
* @param remoteFileName
* @return
* @throws IOException
*/
public static ServerInfo[] getFetchStorages(String groupName,
String remoteFileName)
throws IOException {
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
return trackerClient.getFetchStorages(trackerServer, groupName,
remoteFileName);
}
/***
* 获取Tracker服务地址
* @return
* @throws IOException
*/
public static String getTrackerUrl() throws IOException {
return
"http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+C
lientGlobal.getG_tracker_http_port()+"/";
}
/***
* 获取Storage客户端
* @return
* @throws IOException
*/北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
5.4.3 文件上传
创建一个FileController,在该控制器中实现文件上传操作,代码如下:
*/
private static StorageClient getTrackerClient() throws IOException {
TrackerServer trackerServer = getTrackerServer();
StorageClient storageClient = new StorageClient(trackerServer,
null);
return storageClient;
}
/***
* 获取Tracker
* @return
* @throws IOException
*/
private static TrackerServer getTrackerServer() throws IOException {
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
}
(7)
文件上传
创建一个
FileController
,在该控制器中实现文件上传操作,代码如下:
@RestController
@RequestMapping("/file")
public class FileController {
@PostMapping("/upload")
public Result uploadFile(MultipartFile file){
try{
//判断文件是否存在
if (file == null){
throw new RuntimeException("文件不存在");
}
//获取文件的完整名称
String originalFilename = file.getOriginalFilename();
if (StringUtils.isEmpty(originalFilename)){
throw new RuntimeException("文件不存在");
}
//获取文件的扩展名称 abc.jpg jpg
String extName =
originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
//获取文件内容
byte[] content = file.getBytes();
//创建文件上传的封装实体类
FastDFSFile fastDFSFile = new
FastDFSFile(originalFilename,content,extName);
//基于工具类进行文件上传,并接受返回参数 String[]
String[] uploadResult = FastDFSClient.upload(fastDFSFile);
//封装返回结果
String url =
FastDFSClient.getTrackerUrl()+uploadResult[0]+"/"+uploadResult[1];
return new Result(true,StatusCode.OK,"文件上传成功",url);
}catch (Exception e){
e.printStackTrace();
}
return new Result(false, StatusCode.ERROR,"文件上传失败");
}