基本操作
-
启动
// 服务器启动 fdfs_trackerd /etc/fdfs/tracker.conf //跟踪器启动 fdfs_storaged /etc/fdfs/storage.conf
-
查看启动情况
ps -ef | grep fdfs
-
重启
fdfs_trackerd /etc/fdfs/tracker.conf restart fdfs_storaged /etc/fdfs/storage.conf restart
-
查看数据存储信息
//文件地址对应配置文件的目录地址 ll /fastdfs/storage/files/data/00/00/
-
文件上传测试
//在任意目录下创建txt文件 echo "Hello,FastDFS" > a.txt //上传文件到服务器 fdfs_test /etc/fdfs/client.conf upload 文件路径
-
数据删除
fdfs_delete_file /etc/fdfs/client.conf (group_name)/(remote_filename)
group_name:当前文件的组地址
remote_filename:当前文件的名字
-
关闭
fdfs_trackerd /etc/fdfs/tracker.conf stop fdfs_storaged /etc/fdfs/storage.conf stop
/usr/local/nginx_fdf/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf
整合nginx实现外网访问
-
fastDFS官网下载
fastdfs-nginx-module_v1.16.tar.gz
上传 解压 -
编辑配置文件 进入文件的当前路径 进行修改
vim config
将第一行的local删除即可
- 将FastDFS-nginx-module/src下的mod_fastdfs.conf拷贝至/etc/fdfs/下
cp /usr/local/tmp/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
- 修改conf
vim /etc/fdfs/mod_fastdfs.conf
修改 bath_path、tracker_server、url_have_group_name、store_path0
第一个地址任意、第二个修改为当前服务器的ip地址、第三个改为true 访问时需要带group号、第四个改为storage存放文件的file路径
nginx安装
安装依赖
yum install -y gcc gcc-c++ make libtool wget pcre pcre-devel zlib zlib-devel openssl openssl-devel
创建文件夹
mkdir -p /var/temp/nginx/client
上传tar解压包 运行解压命令
完成之后 运行下列代码
./configure \
--prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/opt/fastdfs-nginx-module/src
module的路径是存放fastdfs_module插件的src路径
运行完之后 查看nginx目录 会多出来makefile的文件
第一遍 执行make命令编译 第二遍执行make install 命令 安装
安装完成之后 修改conf文件
vim /usr/local/nginx/conf/nginx.conf
启动nginx
/usr/local/nginx/sbin/nginx
设置开机启动
vim /etc/rc.d/rc.local
最重要一点
关闭防火墙 否则无法访问
systemctl stop firewalld
然后测试即可
springboot整合fastDFS
- 首先编写配置类
fastdfs_client.conf
放在resources目录下即可
connect_timeout = 2
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = FastDFS1234567890
tracker_server = 192.168.171.224:22122 这里要换成自己的服务器端口
connection_pool.enabled = true
connection_pool.max_count_per_entry = 500
connection_pool.max_idle_time = 3600
connection_pool.max_wait_time_in_ms = 1000
- 然后进行测试即可
@Test
void down() {
try {
// 1.加载配置文件,默认去classpath下加载
ClientGlobal.init("fdfs_client.conf");
// 2.创建TrackerClient对象
TrackerClient trackerClient = new TrackerClient();
// 3.创建TrackerServer对象
TrackerServer trackerServer = trackerClient.getTrackerServer();
// 4.创建StorageServler对象
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
// 5.创建StorageClient对象,这个对象完成对文件的操作
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
// 6.下载文件
String fileName="M00/00/00/wKir4GGwdC6ACJQTAABjNFGdk2o632.png";
String groppName="group1";
byte[] bytes = storageClient.download_file(groppName, fileName);
System.out.println(bytes);
//获取当前路径 下载的文件输出到桌面 也可以将其替换成任意地址
File desktopDir = FileSystemView.getFileSystemView() .getHomeDirectory();
String desktopPath = desktopDir.getAbsolutePath();
// 7.输出到指定位置的文件名
File file = new File(desktopPath+"\\3.png");
FileOutputStream fileOutputStream=new FileOutputStream(file);//窗机输出流
fileOutputStream.write(bytes);//写入数据
fileOutputStream.close();//关闭输出流
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
}
@Test
void upLoad(){
try {
// 1.加载配置文件,默认去classpath下加载
ClientGlobal.init("fdfs_client.conf");
// 2.创建TrackerClient对象
TrackerClient trackerClient = new TrackerClient();
// 3.创建TrackerServer对象
TrackerServer trackerServer = trackerClient.getTrackerServer();
// 4.创建StorageServler对象
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
// 5.创建StorageClient对象,这个对象完成对文件的操作
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
// 6.上传文件(第一个参数:本地文件路径、第二个参数:上传文件的后缀、第三个参数:文件信息)
String[] uploadArray = storageClient.upload_file("G:\\test.png", "png", null);
for (String str : uploadArray) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
}
@Test
void delete(){
try {
// 1.加载配置文件,默认去classpath下加载
ClientGlobal.init("fdfs_client.conf");
// 2.创建TrackerClient对象
TrackerClient trackerClient = new TrackerClient();
// 3.创建TrackerServer对象
TrackerServer trackerServer = trackerClient.getTrackerServer();
// 4.创建StorageServler对象
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
// 5.创建StorageClient对象,这个对象完成对文件的操作
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
// 6.删除文件(返回0表示成功,其它均表示失败)和上传文件一个道理 输入组名和服务器中的文件名
int num = storageClient.delete_file("group1", "M00/00/00/wKir4GGxd9iAar6rAAOHYHzsk8w050.png");
System.out.println(num);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
}
测试过程中发现 许多步骤都是固定的 ,唯一不变的只有进行具体操作时调用的方法,因此再此基础上整理出工具类以供使用
FastDFSUtil
package com.llf.up_and_down.utils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.*;
/**
* @Author llf
* @Date 2021/12/9 13:57
* @Version 1.0
*/public class FastDFSUtils {
/**
* FastDFS 分布式文件系统 Java 客户端工具类
* 具体功能:文件上传、下载、替换、删除、查询文件元数据、查看文件详情
*/
// 获取配置文件地址
private static final String CONF_FILENAME = Thread.currentThread()
.getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
// Storage 存储服务器客户端
private static StorageClient storageClient = null;
static {
try {
// 加载配置文件
ClientGlobal.init("fdfs_client.conf");
// 初始化 Tracker 客户端
TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
// 初始化 Tracker 服务端
TrackerServer trackerServer = trackerClient.getTrackerServer();
// 初始化 Storage 服务端
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
// 初始化 Storage 客户端
storageClient = new StorageClient(trackerServer, storageServer);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
}
/**
* 文件上传
*
* @param inputStream 上传的文件的字节输入流
* @param fileName 上传的文件的原始名
* @return
*/
public static String[] uploadFile(InputStream inputStream, String fileName) {
try {
// 准备字节数组
byte[] fileBuff = null;
// 文件元数据
NameValuePair[] metaList = null;
if (inputStream != null) {
// 查看文件的长度
int len = inputStream.available();
// 初始化元数据数组
metaList = new NameValuePair[2];
// 第一组元数据,文件的原始名称
metaList[0] = new NameValuePair("file_name", fileName);
// 第二组元数据,文件的长度
metaList[1] = new NameValuePair("file_length", String.valueOf(len));
// 创建对应长度的字节数组
fileBuff = new byte[len];
// 将输入流中的字节内容,读到字节数组中
inputStream.read(fileBuff);
}
/*
上传文件。
参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据
*/
String[] fileids = storageClient.upload_file(fileBuff, getFileExt(fileName), metaList);
inputStream.close();
return fileids;
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return null;
}
/**
* 文件上传
*
* @param file 上传的文件
* @param fileName 上传的文件的原始名
* @return
*/
public static String[] uploadFile(File file, String fileName) {
try (
FileInputStream fis = new FileInputStream(file)) {
fis.close();
return uploadFile(fis, fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取文件后缀名(不带点)
*
* @param fileName
* @return 如:"jpg" or ""
*/
private static String getFileExt(String fileName) {
if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
return "";
}
return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
}
/**
* 获取文件详情
*
* @param groupName 组/卷名,默认值:group1
* @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
* @return 文件详情
*/
public static FileInfo getFileInfo(String groupName, String remoteFileName) {
try {
return storageClient.get_file_info(groupName == null ? "group1" : groupName, remoteFileName);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取元数据
*
* @param groupName 组/卷名,默认值:group1
* @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
* @return 文件的元数据数组
*/
public static NameValuePair[] getMetaData(String groupName, String remoteFileName) {
try {
// 根据组名和文件名通过 Storage 客户端获取文件的元数据数组
return storageClient.get_metadata(groupName == null ? "group1" : groupName, remoteFileName);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return null;
}
/**
* 文件下载
*
* @param groupName 组/卷名,默认值:group1
* @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
* @return 文件的字节输入流
*/
public static InputStream downloadFile(String groupName, String remoteFileName) {
try {
// 根据组名和文件名通过 Storage 客户端获取文件的字节数组
byte[] bytes = storageClient.download_file(groupName == null ? "group1" : groupName, remoteFileName);
// 返回字节流对象
InputStream inputStream = new ByteArrayInputStream(bytes);
inputStream.close();
return inputStream;
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return null;
}
/**
* 文件删除
*
* @param groupName 组/卷名,默认值:group1
* @param remoteFileName 文件名,例如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
* @return 0为成功,非0为失败
*/
public static int deleteFile(String groupName, String remoteFileName) {
int result = -1;
try {
// 根据组名和文件名通过 Storage 客户端删除文件
result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return result;
}
/**
* 修改一个已经存在的文件
*
* @param oldGroupName 旧组名
* @param oldFileName 旧文件名
* @param file 新文件
* @param fileName 新文件名
* @return
*/
public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) {
// 先上传
String[] fileids = uploadFile(file, fileName);
if (fileids == null) {
return null;
}
// 再删除
int delResult = deleteFile(oldGroupName, oldFileName);
if (delResult != 0) {
return null;
}
return fileids;
}
}
配合web实现demo
- 前端实现
<form enctype="multipart/form-data" method="post" action="/upLoadImg">
<input type="file" id="info" name="file" >
<input type="submit" value="上传" />
</form>
一个简单的input输入框 这种方式是最容已实现的
- 后端处理
@PostMapping("/upLoadImg")
public String upLoadImg(MultipartFile file,Model model){
try {
/* 获取上传文件名字*/
String filename = file.getOriginalFilename();
/* 截取文件扩展名 */
String extName = filename.substring(filename.lastIndexOf(".") + 1);
/* 使用fastdfs工具类上传图片 */
String[] file1 = FastDFSUtils.uploadFile(file.getInputStream(), filename);
StringBuffer buffer = new StringBuffer();
//这里设置为fastdfs服务器的地址
buffer.append("http://192.168.171.224/");
for (String s : file1) {
// 为组名后面添加 / 与文件名拼接
if (!s.endsWith("png")){
buffer.append(s+"/");
}else {
buffer.append(s);
}
System.out.println(s);
}
String url=String.valueOf(buffer);
model.addAttribute("url",url);
} catch (Exception e) {
e.printStackTrace();
}
return "image";
}
返回新的页面 拿到url的值 进行页面渲染
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img th:src="@{${url}}" alt="刚上传的图片">
<span th:text="${url}"></span>
</body>
</html>
Utils工具类的代码直接复制 修改一下配置文件的地址就可以直接使用