一、 什么是fastDfs
fastDfs是一个轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
二、 为什么要使用fastDfs
在单体应用时代可以使用 apache的common-fileupload或者struts进行文件的上传下载,但是对于海量的数据,文件资源和程序都放在一起会影响性能,特别是针对现在的微服务框架,更需要使用分布式的文件系统去上传,下载图片或者文件,对于海量的文件存储,fastDfs是个不错的选择。
fastDfs有两个重要的部件:
① 跟踪器(tracker)
简单来说就是控制文件上传的路由,负责分配文件的地址,保持周期性心跳。
② 存储节点(storage)
相当于一个存贮的容器,以 group 为单位,每个 group 内可以有多台 storage server。
引用官方的一个原理图
三、 如何安装
安装的教程网上是有很多的,这里不再过多的阐述。
这里针对linux版本的单节点的安装推荐两篇网上的安装教程:
https://blog.csdn.net/zxl315/article/details/53535751
http://www.cnblogs.com/adolfmc/p/4239575.html
主要有这4个配置文件
如果需要配置修改fastDfs的密码的话,可以修改下图的这个地方
四、 如何使用
1. 引入依赖
在javaweb程序中使用的时候,如果项目没有使用maven,需要下载jar包 fastdfs_client_v1.19.jar,然后引入。
如果是maven项目的话,需要在pom.xml文件中引入fastdfs_client 依赖。
<dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>5.0.4</version> </dependency>
2. 配置参数
在src/main/resource 下创建 fdfs_client.conf 配置文件
#fdfs_client.conf 配置
connect_timeout = 10 network_timeout = 30 charset = UTF-8 http.tracker_http_port = 8888 http.anti_steal_token = no http.secret_key = FastDFS1234567890 tracker_server = 192.168.220.88:22122 #如果有多台服务,指定集群的IP #tracker_server = 192.168.220.89:22122 #tracker_server = 192.168.220.90:22122
3. 工具类
1) 初始化
初始化fastDfs的跟踪器和存储器,上传和下载的时候就可以调用这个初始化了。
/** * @Description:初始化fastDfs * @author: jhy * @date: 2017年10月31日 上午9:52:16 */ public static Map<String, Object> init() { Map<String, Object> map = new HashMap<String, Object>(); try { String classPath = new File(FastDfsUtil.class.getResource("/").getFile()).getCanonicalPath(); classPath = URLDecoder.decode(classPath,"utf-8"); String configFilePath = classPath + File.separator + "fdfs_client.conf"; logger.info("配置文件:" + configFilePath); // 初始化参数 ClientGlobal.init(configFilePath); // 初始化跟踪器 TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); // 初始化存储器 StorageServer storageServer = null; StorageClient storageClient = new StorageClient(trackerServer, storageServer); map.put("trackerClient", trackerClient); map.put("trackerServer", trackerServer); map.put("storageClient", storageClient); map.put("storageServer", storageServer); return map; } catch (Exception e) { e.printStackTrace(); } return null; }
2) 上传文件
通过传入file和文件名,上传成功返回上传成功的路径
/** * @Description:上传文件 * @author: jhy * @date: 2017年10月25日 上午9:28:52 * @param:file:上传文件流 */ public static Map<String, Object> upload(File file, String fileName) { Map<String, Object> map = new HashMap<String, Object>(); try { // 初始化fastDfs Map<String, Object> initMap = FastDfsUtil.init(); TrackerClient trackerClient = (TrackerClient) initMap.get("trackerClient"); TrackerServer trackerServer = (TrackerServer) initMap.get("trackerServer"); StorageClient storageClient = (StorageClient) initMap.get("storageClient"); // 初始化参数 NameValuePair[] meta_list = new NameValuePair[3]; meta_list[0] = new NameValuePair("width", "120"); meta_list[1] = new NameValuePair("heigth", "120"); meta_list[2] = new NameValuePair("author", "jhy"); //获取文件后缀名 String prefix = fileName.substring(fileName.lastIndexOf(".") + 1); FileInputStream fis = new FileInputStream(file); byte[] file_buff = null; if(fis != null){ int len = fis.available(); file_buff = new byte[len]; fis.read(file_buff); } logger.info("文件长度: " + file_buff.length); // 声明组 String group_name = null; // 根据跟踪器和组查找存储器 StorageServer[] storageServers = trackerClient.getStoreStorages(trackerServer, group_name); if (storageServers == null) { logger.info("无法找到存储器服务:" + storageClient.getErrorCode()); map.put("resCode", storageClient.getErrorCode()); map.put("resMsg", "无法找到存储器服务"); return map; }else{ logger.info("存储器数量: " + storageServers.length); for (int k = 0; k < storageServers.length; k++){ logger.info("当前文件:"+ k + 1 + ". " + "当前ip和端口" + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); } } // 开始时间 long startTime = System.currentTimeMillis(); // 文件上传返回结果 String[] results = storageClient.upload_file(file_buff, prefix, meta_list); logger.info("上传耗费时间: " + (System.currentTimeMillis() - startTime) + " ms"); if (results == null){ logger.info("上传失败:" + storageClient.getErrorCode()); map.put("resCode", storageClient.getErrorCode()); map.put("resMsg", "上传失败"); return map; } //返回结果赋值给组 group_name = results[0]; String remote_filename = results[1]; logger.info("组名: " + group_name + ", 文件路径: " + remote_filename); logger.info(storageClient.get_file_info(group_name, remote_filename).toString()); //根据跟踪器,组和文件路径查找跟踪服务器 ServerInfo[] servers = trackerClient.getFetchStorages(trackerServer, group_name, remote_filename); if (servers == null){ logger.info("无法找到跟踪器服务:" + storageClient.getErrorCode()); map.put("resCode", trackerClient.getErrorCode()); map.put("resMsg", "无法找到跟踪器服务"); return map; } else { logger.info("跟踪服务器数量: " + servers.length); for (int k = 0; k < servers.length; k++){ logger.info("当前文件:"+ k + 1 + ". " + "当前ip和端口" + servers[k].getIpAddr() + ":" + servers[k].getPort()); } } map.put("resCode", "0000");//代表上传成功 map.put("resMsg", remote_filename); logger.info("上传成功"); trackerServer.close(); return map; } catch (Exception e) { e.printStackTrace(); map.put("resCode", "9999"); map.put("resMsg", "文件服务器连接异常"); } return map; }
3) 获取文件信息
通过传入组名和服务器保存的文件名称获取远程文件信息
/** * @Description:获取文件信息 * @author: jhy * @date: 2017年10月31日 上午9:56:33 * @param:group_name:组名 * @param:remote_filename 文件名称 */ public static Map<String, Object> getFileInfo(String group_name, String remote_filename) { Map<String, Object> map = new HashMap<String, Object>(); try { // 初始化fastDfs Map<String, Object> initMap = FastDfsUtil.init(); StorageClient storageClient = (StorageClient) initMap.get("storageClient"); FileInfo fi = storageClient.get_file_info(group_name, remote_filename); String sourceIpAddr = fi.getSourceIpAddr(); long size = fi.getFileSize(); logger.info("ip地址:" + sourceIpAddr + ",文件大小:" + size); map.put("resCode", "0000");//代表下载成功 map.put("resMsg", fi); logger.info("获取文件信息成功"); return map; } catch (Exception e) { e.printStackTrace(); } return null; }
4) 下载文件
通过组名和文件名下载服务器的文件。
/** * @Description:下载文件 * @author: jhy * @date: 2017年10月31日 上午9:56:33 * @param:group_name:组名 * @param:remote_filename 文件名称 */ public static Map<String, Object> download(String group_name, String remote_filename) { Map<String, Object> map = new HashMap<String, Object>(); try { // 初始化fastDfs Map<String, Object> initMap = FastDfsUtil.init(); StorageClient storageClient = (StorageClient) initMap.get("storageClient"); byte[] b = storageClient.download_file(group_name, remote_filename); logger.info("下载字节b:" + b); if (b != null) { map.put("resCode", "0000");//代表下载成功 map.put("resMsg", b); logger.info("下载成功"); }else { map.put("resCode", "9999");//代表下载失败 map.put("resMsg", b); logger.info("下载失败"); } return map; } catch (Exception e) { e.printStackTrace(); } return null; }
5) 测试
/** * @Description:测试 * @author: jhy * @date: 2017年10月25日 上午11:04:39 */ public static void main(String[] args) { // 上传 // File file = new File("E:\\pic.png"); // FastDfsUtil.upload(file,"E:\\pic.png"); // 下载 FastDfsUtil.download("group1", "M00/00/01/pqYBZVofaPeANx_UAACnTf3PBis648.png"); }
-------------END-------------
如果感觉对自己有帮助的,可以支持一下哈。
本文暂时没有评论,来添加一个吧(●'◡'●)