Mac系统通过Docker搭建FastDFS
Docker构建FastDFS
查找镜像
打开终端通命令查找fastdfs的镜像
docker search fastdfs
拉取镜像
在找到合适的镜像后执行命令:
docker pull delron/fastdfs
准备构建FastDFS的目录
这一步可以自己选择文件映射位置,我这里选择的是~/docker目录下
mkdir -p ~/docker/fastdfs/tracker
mkdir -p ~/docker/fastdfs/storage
chmod -R 777 ~/docker/fastdfs
构建track服务容器
常规命令:
docker run -d --name tracker --network=host -v ~/docker/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
Mac系统命令:
docker run -d --name tracker -p 22122:22122 -v ~/docker/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
注意:
因为Mac系统网络不支持host模式,因此要使用第二种方式构建
构建storage容器
常规命令:
docker run -d --name storage --network=host -e TRACKER_SERVER=192.168.12.78:22122 -e GROUP_NAME=group1 -v ~/docker/fastdfs/storage:/var/fdfs delron/fastdfs storage
Mac系统命令:
docker run -dti --name storage -p 8888:8888 -p 23000:23000 -e TRACKER_SERVER=192.168.12.78:22122 -e GROUP_NAME=group1 -v ~/docker/fastdfs/storage:/var/fdfs delron/fastdfs storage
注意:
因为Mac系统网络不支持host模式,因此要使用第二种方式构建
TRACKER_SERVER写本机ip地址,不能使用127.0.0.1
GROUP_NAME=group1是storage的组名,若新增storage节点可以改成group2
验证FastDFS是否构建成功
在终端中输入命令,查看容器是否正常启动:
docker ps
打开浏览器输入输入ip地址:8888,查看是否能访问到nginx
若以上都能成功表示,FastDFS构建成功
测试FastDFS文件上传
1.拷贝一张图片到storage目录下
cp ~/Desktop/DSC_6716.JPG ~/docker/fastdfs/storage
2.进入storage容器
docker exec -it storage /bin/bash
#进入该目录
cd /etc/fdfs/
3.上传刚刚拷贝来的图片
fdfs_upload_file /etc/fdfs/client.conf /var/fdfs/DSC_6716.JPG
4.在浏览器中预览图片
SpringBoot集成FastDFS
导入maven依赖
<dependency>
<groupId>cn.aghost</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.29.0</version>
</dependency>
在application.yml中增加FastDFS配置
fastdfs:
tracker-servers: 192.168.12.78:22122
增加FastDFS配置类
package com.geek.system.config.fastdfs;
import lombok.extern.slf4j.Slf4j;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.Properties;
/**
* @author Xiaobo
* @ClassName FastDFSConfig
* @Description
* @date 2022/10/11 5:26 下午
*/
@Slf4j
@Component
public class FastDFSConfig {
@Value("${fastdfs.tracker-servers}")
private String trackerServers;
@Bean
public StorageClient storageClient(){
try{
Properties props = new Properties();
props.put(ClientGlobal.PROP_KEY_TRACKER_SERVERS, trackerServers);
ClientGlobal.initByProperties(props);
// 链接FastDFS服务器,创建tracker和Stroage
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getTrackerServer();
StorageServer storageServer=trackerClient.getStoreStorage(trackerServer);
//定义Stroage客户端对象,需要使用这个对象来完成具体的文件上传,下载和删除操作
StorageClient storageClient = new StorageClient(trackerServer,storageServer);
return storageClient;
}catch (Exception e){
log.error("加载StorageClient 异常", e);
}
return null;
}
}
编写FastDFS工具类
package com.geek.system.utils;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.csource.fastdfs.FileInfo;
import org.csource.fastdfs.StorageClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
/**
* @author Xiaobo
* @ClassName FastDFSUtil
* @Description
* @date 2022/10/11 5:41 下午
*/
@Slf4j
@Component
public class FastDFSUtil {
private static StorageClient storageClient;
@Autowired
public void setStorageClient(StorageClient storageClient) {
FastDFSUtil.storageClient = storageClient;
}
/**
* 文件上传
*
* @param file
* @return
*/
public static String fastUpload(MultipartFile file) {
String url = StrUtil.EMPTY;
String ext_name = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(StrUtil.DOT) + 1);
try {
String[] result = storageClient.upload_file(file.getBytes(), ext_name, null);
url = result[0] + "/" + result[1];
} catch (Exception e) {
e.printStackTrace();
log.error("上传文件失败");
}
return url;
}
/**
* 获取文件信息
*
* @param groupName
* @param remoteFileName
* @return
*/
public static FileInfo getFile(String groupName, String remoteFileName) {
//获取文件信息
FileInfo fileInfo = null;
try {
fileInfo = storageClient.get_file_info(groupName, remoteFileName);
} catch (Exception e) {
e.printStackTrace();
log.error("获取文件异常");
}
return fileInfo;
}
/**
* 文件下载
*
* @param downloadFileName 下载文件名称
* @param groupName 组名
* @param remoteFileName 远端文件名称
* @param response
*/
public static void downloadFile(String downloadFileName, String groupName, String remoteFileName, HttpServletResponse response) {
try {
byte[] buffer = storageClient.download_file(groupName, remoteFileName);
response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
response.addHeader("Content-Length", "" + buffer.length);
OutputStream ous = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream;charset=utf-8");
ous.write(buffer);
ous.flush();
ous.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除文件
*
* @param groupName 组名
* @param remoteFileName 远端文件名称
* @return -1失败,0成功 ,2找不到文件
*/
public static int deleteFile(String groupName, String remoteFileName) {
int flag = -1;
try {
int res = storageClient.delete_file(groupName, remoteFileName);
flag = res;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
}
编写文件上传接口
package com.geek.system.controller;
import com.geek.system.utils.FastDFSUtil;
import lombok.RequiredArgsConstructor;
import org.csource.fastdfs.FileInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
/**
* @author Xiaobo
* @ClassName FileController
* @Description
* @date 2022/10/11 5:48 下午
*/
@RestController
@RequestMapping("/v1/file")
@RequiredArgsConstructor
public class FileController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
// ToDo 记录数据库
return FastDFSUtil.fastUpload(file);
}
@GetMapping("/get/file")
public FileInfo getFile(@RequestParam("group_name") String groupName,
@RequestParam("remote_file_name") String remoteFileName) {
return FastDFSUtil.getFile(groupName, remoteFileName);
}
/**
* 下载文件
*
* @param groupName
* @param remoteFileName
* @param response
*/
@GetMapping("/download")
public void downloadFile(@RequestParam("group_name") String groupName,
@RequestParam("remote_file_name") String remoteFileName, HttpServletResponse response) {
// todo 这里的文件名应该随机生成或者从数据库读取,文件扩展名应该从数据库获取,这里只做下载演示,因此固定写死
String downloadFileName = "测试下载文件.JPG";
FastDFSUtil.downloadFile(downloadFileName, groupName, remoteFileName, response);
}
/**
* 删除文件
*
* @param groupName
* @param remoteFileName
* @return -1失败,0成功 ,2找不到文件
*/
@DeleteMapping("/delete")
public int deleteFile(@RequestParam("group_name") String groupName,
@RequestParam("remote_file_name") String remoteFileName) {
return FastDFSUtil.deleteFile(groupName, remoteFileName);
}
}
上传接口测试
发现控制台报错:
引起报错的原因:
因为mac不支持host网络模式造成的,tracker容器配置的docker内部的ip导致的连接不通
解决方法:
进入tracker容器
docker exec -it tracker /bin/bash
编辑storage.conf文件
vi /etc/fdfs/storage.conf
执行以命令
fdfs_monitor /etc/fdfs/storage.conf
退出容器,再宿主机执行命令修改网络的别名
exit #退出容器
#修改网络的别名
sudo ifconfig lo0 alias 172.17.0.1
sudo ifconfig lo0 alias 192.168.12.78
注意
设置网络别名后,所有访问172.17.0.1的都会访问到本机
还原网络设置
sudo ifconfig lo0 -alias 192.168.12.78
sudo ifconfig lo0 -alias 172.17.0.1
再次测试上传文件接口
没有出现报错,并返回了文件的url
测试获取文件信息接口
返回了文件的基本信息
结束
至此关于FastDFS的搭建和SpringBoot的集成就都完成了,若有什么问题欢迎交流探讨,谢谢~