FastDFS的使用
一、安装配置FastDFS
查看容器:docker ps
查看镜像:docker images
进入容器:docker exec -it storage /bin/bash
1、拉取FastDFS镜像
docker pull morunchang/fastdfs
2、运行tracker和storage
tracker:负责文件管理负载均衡操作,控制中心(注册中心)
storage:文件上传、文件下载、文件删除、文件修改……
运行tracker
docker run ‐d ‐‐name tracker ‐‐net=host morunchang/fastdfs sh tracker.sh
运行storage
docker run ‐d ‐‐name storage ‐‐net=host ‐e TRACKER_IP=虚拟机ip:22122 ‐e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh
3、设置开机启动
docker update ==restart=always tracker 设置tracker开机启动
docker update ==restart=always storage 设置storage开机启动
reboot 重启
4、修改nginx配置
进入storage容器内部,修改nginx.conf
docker exec -it storage /bin/bash
进入后
vi /etc/nginx/conf/nginx.conf
安装运行tracker和storage时默认已经安装配置好了nginx
server {
listen 8080;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location ~ /M00 {
root /data/fast_data/data;
ngx_fastdfs_module;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
二、文件存储微服务
1、创建maven工程changgou-service-file
导入依赖
<!--fastdfs客户端-->
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
创建tracker配置文件fdfs_client.conf
#tracker配置信息
#连接操作时间
connect_timeout = 60
#网络请求操作时间
network_timeout = 60
charset = UTF‐8
#tracker的http请求端口
http.tracker_http_port = 8080
#tracker的TCP通信端口
tracker_server = 虚拟机IP:22122
创建核心配置文件application.yml
spring:
servlet:
multipart:
#上传文件最大大小
max-file-size: 10MB
#请求数据最大大小
max-request-size: 10MB
#服务名:file
application:
name: file
server:
port: 18084
eureka:
client:
#eureka注册地址
service‐url:
defaultZone:http://127.0.0.1:7001/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
创建启动类FileApplication
//exclude:排除数据库自动加载
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient // 开启Eureka服务 客户端
public class FileApplication {
// 引导类
public static void main(String[] args) {
//这里会创建spring容器
SpringApplication.run(FileApplication.class, args);
}
}
创建文件上传信息FastDFSFile,封装类
/**
* @Author TeaBowl
* @Date 2020/11/2 17:46
* @Version 1.0
* 封装文件上传信息
* 时间:
* Author:
* type:
* size:
* 附加信息:
* 文件内容->文件的字节数组
*/
@Data //getter&setter方法
public class FastDFSFile implements Serializable {
//文件名字
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 md5, String author) {
this.name = name;
this.content = content;
this.ext = ext;
this.md5 = md5;
this.author = author;
}
public FastDFSFile(String name, byte[] content, String ext) {
this.name = name;
this.content = content;
this.ext = ext;
}
}
创建工具类FastDFSUtil
优化代码:抽取公共代码
测试
/**
* @Author TeaBowl @Date 2020/11/2 17:58 @Version 1.0
* 实现FastDFS文件管理
* 文件上传 文件下载 文件删除 文件信息获取 Storage信息获取 Tracker信息获取
*/
public class FastDFSUtil {
/**
* 初始化加载Tracker连接信息
*/
static {
try {
// tracker的配置信息:fdfs_client.conf
// 查找classpath下的文件路径
String filename = new ClassPathResource("fdfs_client.conf").getPath();
// 加载Tracker连接信息
ClientGlobal.init(filename);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件上传
*
* @param fastDFSFile :上传的文件信息封装
* @return
*/
public static String[] upload(FastDFSFile fastDFSFile) throws Exception {
// 附加参数
NameValuePair[] metaList = new NameValuePair[1];
metaList[0] = new NameValuePair("拍摄地址", "西安大雁塔");
// 获取TrackerServer
TrackerServer trackerServer = getTrackerServer();
// 获取StotageClient
StorageClient storageClient = getStorageClient(trackerServer);
/**
* 通过StorageClient访问Storage,实现文件上传,并且获取文件上传后的存储信息 上传文件的字节数组 文件的扩展名 附加参数
*
* <p>uploads[] uploads[0]:文件上传所存储的Storage的组名 group1 uploads[1]:文件上传所存储的Storage的文件名
* M00/02/44/chawaner.jpg
*/
String[] uploads =
storageClient.upload_file(fastDFSFile.getContent(), fastDFSFile.getExt(), metaList);
return uploads;
}
/**
* 获取文件信息
*
* @param groupName :组名 group1
* @param remoteFileName :文件存储路径 M00/00/00/wKiNb1-f9KWAFfThAACrggZCTjU215.png
* @return file_info:文件信息
* @throws Exception
*/
public static FileInfo getFile(String groupName, String remoteFileName) throws Exception {
// 获取TrackerServer
TrackerServer trackerServer = getTrackerServer();
// 获取StotageClient
StorageClient storageClient = getStorageClient(trackerServer);
// 获取文件信息
FileInfo file_info = storageClient.get_file_info(groupName, remoteFileName);
return file_info;
}
/**
* 文件下载
*
* @param groupName :组名 group1
* @param remoteFileName :文件存储路径 M00/00/00/wKiNb1-f9KWAFfThAACrggZCTjU215.png
* @throws Exception
* @return
*/
public static InputStream downloadFile(String groupName, String remoteFileName) throws Exception {
// 获取TrackerServer
TrackerServer trackerServer = getTrackerServer();
// 获取StotageClient
StorageClient storageClient = getStorageClient(trackerServer);
// 文件下载 字节数组->字节输入流
byte[] buffer = storageClient.download_file(groupName, remoteFileName);
ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
return inputStream;
}
/**
* 删除文件
*
* @throws Exception
*/
public static void deleteFile(String groupName, String remoteFileName) throws Exception {
// 获取TrackerServer
TrackerServer trackerServer = getTrackerServer();
// 获取StotageClient
StorageClient storageClient = getStorageClient(trackerServer);
// 删除文件
storageClient.delete_file(groupName, remoteFileName);
}
/**
* 获取Storage信息
*
* @throws Exception
* @return
*/
public static StorageServer getStorages() throws Exception {
// 创建一个Tracker访问的客户端对象TrackerClient
TrackerClient trackerClient = new TrackerClient();
// 通过TrackerClient访问TrackerServer服务,获取连接信息
TrackerServer trackerServer = trackerClient.getConnection();
// 获取storage信息
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
return storageServer;
}
/**
* 获取Storage组的IP和端口信息
*
* @return
*/
public static ServerInfo[] getServerInfo(String groupName, String remoteFileName)
throws Exception {
// 创建一个Tracker访问的客户端对象TrackerClient
TrackerClient trackerClient = new TrackerClient();
// 通过TrackerClient访问TrackerServer服务,获取连接信息
TrackerServer trackerServer = trackerClient.getConnection();
// 通过TackerServer的连接信息可以获取Storage的连接信息,创建StorageClient对象存储Storage的连接信息
StorageClient storageClient = new StorageClient(trackerServer, null);
// 获取storage组的IP和端口信息
ServerInfo[] serverInfos =
trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
return serverInfos;
}
/**
* 获取Tracker信息
*
* @throws Exception
* @return
*/
public static String getTrackerInfo() throws Exception {
// 获取TrackerServer
TrackerServer trackerServer = getTrackerServer();
// 获取Tracker信息:IP、HTTP端口
String ip = trackerServer.getInetSocketAddress().getHostString();
// 8080
int port = ClientGlobal.getG_tracker_http_port();
String url = "http://" + ip + ":" + port;
return url;
}
/**
* 抽取的 获取TrackerServer代码
*
* @return
* @throws Exception
*/
public static TrackerServer getTrackerServer() throws Exception {
// 创建一个Tracker访问的客户端对象TrackerClient
TrackerClient trackerClient = new TrackerClient();
// 通过TrackerClient访问TrackerServer服务,获取连接信息
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
/**
* 抽取的 获取storageClient代码
*
* @return
* @throws Exception
*/
public static StorageClient getStorageClient(TrackerServer trackerServer) throws Exception {
// 通过TackerServer的连接信息可以获取Storage的连接信息,创建StorageClient对象存储Storage的连接信息
StorageClient storageClient = new StorageClient(trackerServer, null);
return storageClient;
}
// 主方法 测试
public static void main(String[] args) throws Exception {
// 获取文件信息
/*FileInfo fileInfo = getFile("group1", "M00/00/00/wKiNb1-f9KWAFfThAACrggZCTjU215.png");
System.out.println("文件所在IP:" + fileInfo.getSourceIpAddr());
System.out.println("文件大小:" + fileInfo.getFileSize());*/
// 文件下载
/*// 获取文件输入流
InputStream is = downloadFile("group1", "M00/00/00/wKiNb1-f9KWAFfThAACrggZCTjU215.png");
// 将文件写入到本地磁盘 文件存储至本地磁盘的位置
FileOutputStream os = new FileOutputStream("D:/fileDownload.png");
// 定义一个缓冲区
byte[] buffer = new byte[1024];
// 读取文件输入流到缓冲区 判断是否有数据 !=-1就是有数据
while (is.read(buffer) != -1) {
// 缓冲区写入到本地磁盘 1024个字节写入到fileDownload.png
os.write(buffer);
}
// 刷新缓冲区
os.flush();
// 关闭输出流 os
os.close();
// 关闭输入流 is
is.close();*/
// 文件删除
// deleteFile("group1", "M00/00/00/wKiNb1-g0PWAFOI2AASGb8jq9KQ512.jpg");
// 获取storage信息
/*StorageServer storageServer = getStorages();
System.out.println("获取下标:"+storageServer.getStorePathIndex());
System.out.println("获取IP信息:"+storageServer.getInetSocketAddress().getHostString());*/
// 获取Storage组的IP和端口信息
// Storage组名
/*ServerInfo[] groups = getServerInfo("group1", "M00/00/00/wKiNb1-g1dKAWDCkAASGb8jq9KQ172.jpg");
for (ServerInfo group : groups) {
// 获取IP
System.out.println(group.getIpAddr());
// 获取端口
System.out.println(group.getPort());
}*/
// 获取Tracker信息
// System.out.println(getTrackerInfo());
}
}
文件删除方法,要在服务器的storage配置里加上下面这句,添加头信息:不要缓存
location ~ /M00 {
add_header Cache-Control no-store;
root /data/fast_data/data;
ngx_fastdfs_module;
}
重启storage
exit
docker restart storage
创建FileUploadController
动态获取url:FastDFSUtil.getTrackerInfo()
@RestController
@RequestMapping(value = "/upload")
@CrossOrigin // 跨域
public class FileUploadController {
/**
* 文件上传
*
* @param file:前端传来的参数
* @return
*/
@PostMapping
public Result upload(@RequestParam(value = "file")MultipartFile file) throws Exception {
/** 封装文件信息 文件名 文件字节数组 文件扩展名 */
FastDFSFile fastDFSFile = new FastDFSFile(
file.getOriginalFilename(),
file.getBytes(),
StringUtils.getFilenameExtension(file.getOriginalFilename()));
// 调用FastDFSUtil工具类将文件传入到FastDFS中
String[] uploads = FastDFSUtil.upload(fastDFSFile);
//拼接访问地址:url = http://192.168.141.111:8080/group1/M00/00/00/mksnjdlkakjiodnsjbja.jpg
//String url = "http://192.168.141.111:8080"+"/"+uploads[0]+"/"+uploads[1];
String url = FastDFSUtil.getTrackerInfo()+"/"+uploads[0]+"/"+uploads[1];
return new Result(true, StatusCode.OK, "上传成功!",url);
}
}