前言
记录下整个学习过程,fastdfs的介绍就不在赘述。直接上手命令。
开始
拉取镜像
有一点慢,可能需要五六分钟。
docker pull morunchang/fastdfs
运行tracker
没有使用数据卷命令备份,如果需要主要是nginx的log文件,data/fast_data/data下面的文件,以及一些配置文件的备份。
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的配置
进入storage容器内部
docker exec -it storage /bin/bash
里面的几个文件需要我们关注。
- cd /etc/nginx/conf/ 这个目录下,存放着nginx的配置,当我们的端口出现冲突,需要在这里进行修改。
- cd /data/fast_data/data 这个目录下,存放着根据hash算法创建的目录,随机存放文件。
- cd /etc/fdfs/client.conf 这个目录下,我们手动上传文件需要更改里面的ip,否则无法手动上传,当然如果是Java代码上传,则无影响。
- cd /data/nginx/conf/nginx.conf 这个目录下,是storage的nginx配置,我们可以进行小部分配置。
- cd /etc/fdfs/http.conf 这个文件,设置权限的配置,打开token。
现在,我们进行上面的配置修改:
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://192.168.2.152;
expires 30d;
}
查看nginx的配置
cat /etc/nginx/conf/
最主要这几个配置
# the base path to store data and log files
base_path=/data/fast_data
# the paths must be exist
store_path0=/data/fast_data
# "host:port", host can be hostname or ip address
tracker_server=192.168.2.152:22122
修改ip
vim /etc/fdfs/client.conf
这个ip要和虚拟机一致,否则无法上传文件。
退出容器
exit
重启容器
docker restart storage
上传图片测试
查看容器完整ID
docker inspect -f '{{.ID}}' storage
上传图片
docker cp /root/d236fe76-8594-442d-af60-306c99cda817.png 2928a1550310f7a32011d3c5a9f069d32317a154f323020085bfa13f28f757f8:/data/fastdfs/conf/d236fe76-8594-442d-af60-306c99cda817.png
上传
docker exec -it storage /bin/bash
fdfs_upload_file /etc/fdfs/client.conf d236fe76-8594-442d-af60-306c99cda817.png
查看防火墙状态
firewall-cmd --state
停止防火墙
systemctl stop firewalld
Java
fdfs_client.properties
connect_timeout = 60
network_timeout = 60
charset = UTF-8
http.tracker_http_port = 9888 # 这个必须和nginx.conf设置的端口一致,否则无法访问
tracker_server = 192.168.2.152:22122 # 这个ip必须和虚拟机ip一致
application.yml
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
FileApplication
package com.hikktn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ClassName FileApplication
* @Description TODO
* @Author lisonglin
* @Date 2021/5/23 17:49
* @Version 1.0
*/
@SpringBootApplication
public class FileApplication {
public static void main(String[] args) {
SpringApplication.run(FileApplication.class);
}
}
FastDFSFile
package com.hikktn.pojo;
/**
* @ClassName FastDFSFile
* @Description TODO
* @Author lisonglin
* @Date 2021/5/23 17:55
* @Version 1.0
*/
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) {
super();
this.name = name;
this.content = content;
this.ext = ext;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
public String getExt() {
return ext;
}
public void setExt(String ext) {
this.ext = ext;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
FastDFSClient
package com.hikktn.util;
import com.hikktn.pojo.FastDFSFile;
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.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
/**
* @ClassName FastDFSClient
* @Description TODO
* @Author lisonglin
* @Date 2021/5/23 17:50
* @Version 1.0
*/
public class FastDFSClient {
private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);
/***
* 初始化加载FastDFS的TrackerServer配置
*/
static {
try {
String filePath = new ClassPathResource("fdfs_client.properties").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)文件作者
*/
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;
}
/***
* 获取Tracker服务地址
* @return
* @throws IOException
*/
public static String getTrackerUrl() throws IOException {
return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/";
}
/***
* 获取Storage客户端
* @return
* @throws IOException
*/
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;
}
}
FileController
package com.hikktn.controller;
import com.hikktn.pojo.FastDFSFile;
import com.hikktn.util.FastDFSClient;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* @ClassName FileController
* @Description TODO
* @Author lisonglin
* @Date 2021/5/23 18:16
* @Version 1.0
*/
@RestController
public class FileController {
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
String path = "";
try {
path = saveFile(file);
System.out.println(path);
} catch (Exception e) {
e.printStackTrace();
}
return path;
}
/**
* @param multipartFile
* @return
* @throws IOException
*/
public String saveFile(MultipartFile multipartFile) throws IOException {
//1. 获取文件名
String fileName = multipartFile.getOriginalFilename();
//2. 获取文件内容
byte[] content = multipartFile.getBytes();
//3. 获取文件扩展名
String ext = "";
if (fileName != null && !"".equals(fileName)) {
ext = fileName.substring(fileName.lastIndexOf(".") + 1);
}
//4. 创建文件实体类对象
FastDFSFile fastDFSFile = new FastDFSFile(fileName, content, ext);
//5. 上传
String[] uploadResults = FastDFSClient.upload(fastDFSFile);
//6. 拼接上传后的文件的完整路径和名字, uploadResults[0]为组名, uploadResults[1]为文件名称和路径
String path = FastDFSClient.getTrackerUrl() + uploadResults[0] + "/" + uploadResults[1];
//7. 返回
return path;
}
}
测试
填写Headers
Key:Content-Type
Value:multipart/form-data
测试成功!