环境准备
# 关闭防火墙
systemctl disable --now firewalld
systemctl disable --now dnsmasq
systemctl disable --now NetworkManager
# 关闭selinux
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
# 关闭分区
swapoff -a && sysctl -w vm.swappiness=0
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y
磁盘目录
mkdir /home/dfs #创建数据存储目录
cd /usr/local/src #切换到安装目录准备下载安装包
安装 libfastcommon
git clone https://github.com/happyfish100/libfastcommon.git --depth 1
cd libfastcommon/
./make.sh && ./make.sh install #编译安装
安装 FastDFS
cd ../ #返回上一级目录
git clone https://github.com/happyfish100/fastdfs.git --depth 1
cd fastdfs/
./make.sh && ./make.sh install #编译安装
#配置文件准备
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf #客户端文件,测试用
cp /usr/local/src/fastdfs/conf/http.conf /etc/fdfs/ #供nginx访问使用
cp /usr/local/src/fastdfs/conf/mime.types /etc/fdfs/ #供nginx访问使用
安装 fastdfs-nginx-module
cd ../ #返回上一级目录
git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1
cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs
安装 nginx
wget http://nginx.org/download/nginx-1.15.4.tar.gz #下载nginx压缩包
tar -zxvf nginx-1.15.4.tar.gz #解压
cd nginx-1.15.4/
#添加fastdfs-nginx-module模块
./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/
make && make install #编译安装
tracker配置(单机版)
#服务器ip为 192.168.52.1
#我建议用ftp下载下来这些文件 本地修改
vim /etc/fdfs/tracker.conf
#需要修改的内容如下
port=22122 # tracker服务器端口(默认22122,一般不修改)
base_path=/home/dfs # 存储日志和数据的根目录
storage配置(单机版)
vim /etc/fdfs/storage.conf
#需要修改的内容如下
port=23000 # storage服务端口(默认23000,一般不修改)
base_path=/home/dfs # 数据和日志文件存储根目录
store_path0=/home/dfs # 第一个存储目录
tracker_server=192.168.52.1:22122 # tracker服务器IP和端口
http.server_port=8888 # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)
client测试(单机版)
vim /etc/fdfs/client.conf
#需要修改的内容如下
base_path=/home/dfs
tracker_server=192.168.52.1:22122 #tracker服务器IP和端口
#保存后测试,返回ID表示成功 如:group1/M00/00/00/xx.tar.gz
fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/nginx-1.15.4.tar.gz
配置nginx访问(单机版)
vim /etc/fdfs/mod_fastdfs.conf
#需要修改的内容如下
tracker_server=192.168.52.1:22122 #tracker服务器IP和端口
url_have_group_name=true
store_path0=/home/dfs
#配置nginx.config
vim /usr/local/nginx/conf/nginx.conf
#添加如下配置
server {
listen 8888; ## 该端口为storage.conf中的http.server_port相同
server_name localhost;
location ~/group[0-9]/ {
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#测试下载,用外部浏览器访问刚才已传过的nginx安装包,引用返回的ID
http://192.168.182.128:8888/group1/M00/00/00/wKgAQ1pysxmAaqhAAA76tz-dVgg.tar.gz
tracker配置(分布式版)
#服务器ip为 192.168.52.2,192.168.52.3,192.168.52.4
#我建议用ftp下载下来这些文件 本地修改
vim /etc/fdfs/tracker.conf
#需要修改的内容如下
port=22122 # tracker服务器端口(默认22122,一般不修改)
base_path=/home/dfs # 存储日志和数据的根目录
storage配置(分布式版)
vim /etc/fdfs/storage.conf
#需要修改的内容如下
port=23000 # storage服务端口(默认23000,一般不修改)
base_path=/home/dfs # 数据和日志文件存储根目录
store_path0=/home/dfs # 第一个存储目录
tracker_server=192.168.52.2:22122 # 服务器1
tracker_server=192.168.52.3:22122 # 服务器2
tracker_server=192.168.52.4:22122 # 服务器3
http.server_port=8888 # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)
client测试(分布式版)
vim /etc/fdfs/client.conf
#需要修改的内容如下
base_path=/home/moe/dfs
tracker_server=192.168.52.2:22122 # 服务器1
tracker_server=192.168.52.3:22122 # 服务器2
tracker_server=192.168.52.4:22122 # 服务器3
#保存后测试,返回ID表示成功 如:group1/M00/00/00/xx.tar.gz
fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/nginx-1.15.4.tar.gz
配置nginx访问(分布式版)
vim /etc/fdfs/mod_fastdfs.conf
#需要修改的内容如下
tracker_server=192.168.52.2:22122 # 服务器1
tracker_server=192.168.52.3:22122 # 服务器2
tracker_server=192.168.52.4:22122 # 服务器3
url_have_group_name=true
store_path0=/home/dfs
#配置nginx.config
vim /usr/local/nginx/conf/nginx.conf
#添加如下配置
server {
listen 8888; ## 该端口为storage.conf中的http.server_port相同
server_name localhost;
location ~/group[0-9]/ {
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
tracker(启动、重启、停止)
/etc/init.d/fdfs_trackerd start #启动tracker服务
/etc/init.d/fdfs_trackerd restart #重启动tracker服务
/etc/init.d/fdfs_trackerd stop #停止tracker服务
chkconfig fdfs_trackerd on #自启动tracker服务
storage(启动、重启、停止)
/etc/init.d/fdfs_storaged start #启动storage服务
/etc/init.d/fdfs_storaged restart #重动storage服务
/etc/init.d/fdfs_storaged stop #停止动storage服务
chkconfig fdfs_storaged on #自启动storage服务
nginx(启动、重启、停止)
/usr/local/nginx/sbin/nginx #启动nginx
/usr/local/nginx/sbin/nginx -s reload #重启nginx
/usr/local/nginx/sbin/nginx -s stop #停止nginx
# 访问
http://192.168.86.128:8888/group1/M00/00/00/wKjfgl3ijiWATv7JAAA0OhyYlyM226.png
检测集群
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
集成 SpringBoot
pom.xml
<!-- FastDFS分布式文件系统 -->
<!-- https://mvnrepository.com/artifact/com.github.tobato/fastdfs-client -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
application.yml
server:
port: 8001
spring:
servlet: #限制文件上传配置
multipart:
enabled: true #启用文件上传功能
max-file-size: 10MB #设置单个文件的大小
max-request-size: 20MB #设置文件总大小
file-size-threshold: 512KB #当文件超过指定的大小时会返回磁盘
location: / #设置文件上传的临时路径
#配置FastDFS
fdfs:
so-timeout: 2500 #请求超时时间
connect-timeout: 600 #连接超时时间
thumb-image: #缩略图大小
height: 60
width: 60
tracker-list: #tracker地址
- 192.168.223.130:22122
boot:
upload:
baseUrl: http://192.168.86.128/
allowTypes:
- image/jpeg
- image/png
- image/bmp
- image/jpg
FastDFSClientImporter.java
/**
* @className: FastDFSClientImporter
* @author: q-linyu
* @description: FastDFS客户端注入组件类
* 解决JMX重复注册Bean的问题:@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
* @date: 2021/7/18 01:45
* @version: 1.0
**/
@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
public class FastDFSClientImporter {
}
UploadProperty.java
/**
* @className: upload
* @author: q-linyu
* @description: 图片属性配置类
* @date: 2021/7/18 01:49
* @version: 1.0
**/
@Data
@Component
@ConfigurationProperties(prefix="boot.upload")
public class UploadProperty {
/**
* 路径
*/
private String baseUrl;
/**
* 图片格式类型
*/
private List<String> allowTypes;
}
FastDFSUtils.java
/**
* @className: FastDFSUtils
* @author: q-linyu
* @description: 分布式文件系统工具类
* @date: 2021/7/18 01:40
* @version: 1.0
**/
@Component
@EnableConfigurationProperties(UploadProperty.class)
public class FastDFSUtils {
@Autowired
private FastFileStorageClient storageClient;
@Autowired
private UploadProperty uploadProperty;
/**
* 文件上传,并且上传后返回给文件的路径
* @param files 要上传的目标路径
* @return
*/
public List<String> upload(List<MultipartFile> files){
List<String> paths = new ArrayList<>();
files.forEach(file -> {
try {
//校验文件格式
String contentType=file.getContentType();
if (!uploadProperty.getAllowTypes().contains(contentType)) {
// 错误消息的展示----无效的文件类型
}
//获取文件的名称
String fileName=file.getOriginalFilename();
//获取图片的后缀
String prefixName=StringUtils.substringAfter(fileName, ".");
//校验文件的内容
BufferedImage image= ImageIO.read(file.getInputStream());
if (image==null) {
// 错误消息的展示----无效的文件类型
}
//上传FastDFS文件服务器
StorePath storePath=storageClient.uploadFile(file.getInputStream(), file.getSize(), prefixName, null);
paths.add(uploadProperty.getBaseUrl()+storePath.getFullPath());
}catch (IllegalStateException | IOException e) {
//上传失败提示
e.printStackTrace();
}
});
return paths;
}
/**
* 下载文件
* @param filePath
* @param request
* @param response
*/
public void download(String filePath, HttpServletRequest request , HttpServletResponse response){
InputStream is = null;
try {
String[] paths = filePath.split("/");
String groupName = null;
for (String path : paths) {
if (path.contains("group")){
groupName = path;
break;
}
}
assert groupName != null;
String path = filePath.substring(filePath.indexOf(groupName) + groupName.length() + 1);
// 执行下载并返回流
is = storageClient.downloadFile(groupName, path, inputStream -> inputStream);
// 获取带后缀的文件名
String fileName = paths[paths.length - 1];
// 获取类型
String contentType = request.getServletContext().getMimeType(fileName);
String contentDisposition = "attachment;filename=" + fileName;
// 设置请求头
response.setHeader("Content-Type",contentType);
response.setHeader("Content-Disposition",contentDisposition);
// 获取客户端的流
ServletOutputStream os = response.getOutputStream();
// 输出
IOUtils.copy(is,os);
}catch (IOException e){
e.printStackTrace();
}finally {
if (is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 删除文件
* @param filePath
*/
public void delete(String filePath){
storageClient.deleteFile(filePath);
}
}
UploadController.java
/**
* @className: UploadController
* @author: q-linyu
* @description: 文件上传控制器
* @date: 2021/7/18 01:51
* @version: 1.0
**/
@RestController
public class UploadController {
@Autowired
private FastDFSUtils fastDFSUtils;
/**
* 上传文件
* @param files
* @return
*/
@PostMapping(value = "upload")
public List<String> upload(@RequestParam(value = "files")List<MultipartFile> files){
return fastDFSUtils.upload(files);
}
/**
* 下载文件
* @param filePath
* localhost:8001/filePath=http://192.168.223.130/group1/M00/00/00/wKjfgl2oOQSAQXt8AAA0OhyYlyM329.png
* @return
*/
@GetMapping(value = "download")
public void download(@RequestParam(value = "filePath")String filePath, HttpServletRequest request, HttpServletResponse response){
fastDFSUtils.download(filePath,request,response);
}
/**
* 删除文件
* @param filePath
* @return
*/
@DeleteMapping(value = "delete")
public void delete(@RequestParam(value = "filePath")String filePath){
fastDFSUtils.delete(filePath);
}
}