分布式文件服务器FastDFS
1、什么是FastDFS
FastDFS 是用 c 语言编写的一款开源的分布式文件系统。FastDFS 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。
Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。
Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。
图解:
本文省略了FastDFS在linux系统中的安装
2、上传流程
3、下载流程
4、上传小demo
a、导入依赖
<!-- 文件上传组件 --> <dependency> <groupId>org.csource.fastdfs</groupId> <artifactId>fastdfs</artifactId> </dependency>
b、写fdfs_client.conf配置文件
# connect timeout in seconds
# default value is 30s
connect_timeout=30
# network timeout in seconds
# default value is 30s
network_timeout=60
# the base path to store log files
base_path=/home/fastdfs
# tracker_server can ocur more than once, and tracker_server format is
# "host:port", host can be hostname or ip address
tracker_server=192.168.200.128:22122
#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info
# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false
# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600
# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false
# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id = false
# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename = storage_ids.conf
#HTTP settings
http.tracker_server_port=80
#use "#include" directive to include HTTP other settiongs
##include http.conf
c、测试类
// 1、加载配置文件,配置文件中的内容就是 tracker 服务的地址。 ClientGlobal.init("D:/maven_work/fastDFS-demo/src/fdfs_client.conf"); // 2、创建一个 TrackerClient 对象。直接 new 一个。 TrackerClient trackerClient = new TrackerClient(); // 3、使用 TrackerClient 对象创建连接,获得一个 TrackerServer 对象。 TrackerServer trackerServer = trackerClient.getConnection(); // 4、创建一个 StorageServer 的引用,值为 null StorageServer storageServer = null; // 5、创建一个 StorageClient 对象,需要两个参数 TrackerServer 对象、StorageServer 的引用 StorageClient storageClient = new StorageClient(trackerServer, storageServer); // 6、使用 StorageClient 对象上传图片。 //扩展名不带“.” String[] strings = storageClient.upload_file("D:/pic/7.jpg", "jpg", null); // 7、返回数组。包含组名和图片的路径。 for (String string : strings) { System.out.println(string); }
d、测试
c步骤中,控制台输出得到
在浏览器中输入:
http://192.168.200.128/group1/M00/00/03/wKgZhVykfa2AD3IqAACz2X_K6i4287.jpg 测试,如果能获取到上传的图片就说明成功
5、下载小demo
3、优乐选分布式项目中使用FastDFS
a、导入依赖
同上小demo
b、配置文件
同上小demo
c、前台发送请求
app.service("uploadService",function($http){ this.uploadFile = function(){ // 向后台传递数据: var formData = new FormData(); // 向formData中添加数据: formData.append("file",file.files[0]); return $http({ method:'post', url:'../upload/uploadFile.do', data:formData, headers:{'Content-Type':undefined},// Content-Type : text/html text/plain transformRequest: angular.identity }); } });
d、后台调用写好的工具类进行文件上传
工具类代码:
package cn.lqc.core.utils; import org.csource.common.NameValuePair; import org.csource.fastdfs.ClientGlobal; import org.csource.fastdfs.StorageClient1; import org.csource.fastdfs.StorageServer; import org.csource.fastdfs.TrackerClient; import org.csource.fastdfs.TrackerServer; public class FastDFSClient { private TrackerClient trackerClient = null; private TrackerServer trackerServer = null; private StorageServer storageServer = null; private StorageClient1 storageClient = null; public FastDFSClient(String conf) throws Exception { if (conf.contains("classpath:")) { conf = conf.replace("classpath:", this.getClass().getResource("/").getPath()); } ClientGlobal.init(conf); trackerClient = new TrackerClient(); trackerServer = trackerClient.getConnection(); storageServer = null; storageClient = new StorageClient1(trackerServer, storageServer); } /** * 上传文件方法 * <p>Title: uploadFile</p> * <p>Description: </p> * @param fileName 文件全路径 * @param extName 文件扩展名,不包含(.) * @param metas 文件扩展信息 * @return * @throws Exception */ public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception { String result = storageClient.upload_file1(fileName, extName, metas); return result; } public String uploadFile(String fileName) throws Exception { return uploadFile(fileName, null, null); } public String uploadFile(String fileName, String extName) throws Exception { return uploadFile(fileName, extName, null); } /** * 上传文件方法 * <p>Title: uploadFile</p> * <p>Description: </p> * @param fileContent 文件的内容,字节数组 * @param extName 文件扩展名 * @param metas 文件扩展信息 * @return * @throws Exception */ public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception { String result = storageClient.upload_file1(fileContent, extName, metas); return result; } public String uploadFile(byte[] fileContent) throws Exception { return uploadFile(fileContent, null, null); } public String uploadFile(byte[] fileContent, String extName) throws Exception { return uploadFile(fileContent, extName, null); } }
controller中代码:
package cn.lqc.core.controller; import cn.lqc.core.pojo.entity.Result; import cn.lqc.core.utils.FastDFSClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/upload") public class UploadController { //注入文件服务器地址,也就是linux服务器上的ip地址 @Value("${FILE_SERVER_URL}") private String FILE_SERVER_URL; @RequestMapping("/uploadFile") public Result uploadFile(MultipartFile file){ //1.获取文件扩展名 String originalFilename = file.getOriginalFilename(); String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1); try{ //1.创建FastDFS客户端 FastDFSClient fastDFSClient = new FastDFSClient("classpath:fastDFS/fdfs_client.conf"); //在工具类执行上传,返回一个文件路径 String path = fastDFSClient.uploadFile(file.getBytes(), extName); //返回给前台的地址:文件服务器地址+在服务器中的地址 String image_entity_url = FILE_SERVER_URL +path; return new Result(true,image_entity_url); }catch(Exception ex){ ex.printStackTrace(); return new Result(false,"上传失败"); } } }