FastDFS架构包括 Tracker server和Storage server。客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载。
Tracker server作用是负载均衡和调度,通过Tracker server在文件上传时可以根据一些策略找到Storage server提供文件上传服务。可以将tracker称为追踪服务器或调度服务器。
Storage server作用是文件存储,客户端上传的文件最终存储在Storage服务器上,Storage server没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。可以将storage称为存储服务器。
FastDFS集群中的Tracker server可以有多台,Tracker server之间是相互平等关系同时提供服务,Tracker server不存在单点故障。客户端请求Tracker server采用轮询方式,如果请求的tracker无法提供服务则换另一个tracker。
一般会在在每个tracker上安装nginx,的主要目的是做负载均衡及实现高可用。如果只有一台tracker服务器可以不配置nginx。
Storage集群采用了分组存储方式。storage集群由一个或多个组构成,集群存储总容量为集群中所有组的存储容量之和。一个组由一台或多台存储服务器组成,组内的Storage server之间是平等关系,不同组的Storage server之间不会相互通信,同组内的Storage server之间会相互连接进行文件同步,从而保证同组内每个storage上的文件完全一致的。一个组的存储容量为该组内存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是一致的。
采用分组存储方式的好处是灵活、可控性较强。比如上传文件时,可以由客户端直接指定上传到的组也可以由tracker进行调度选择。一个分组的存储服务器访问压力较大时,可以在该组增加存储服务器来扩充服务能力(纵向扩容)。当系统容量不足时,可以增加组来扩充存储容量(横向扩容)。
Storage server会连接集群中所有的Tracker server,定时向他们报告自己的状态,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。
4.1、文件上传
客户端上传文件后存储服务器将文件ID返回给客户端,此文件ID用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。
4.2、文件下载
tracker根据请求的文件路径即文件ID 来快速定义文件。
5.1、引入jar包
<dependency> <groupId>org.csource.fastdfs</groupId> <artifactId>fastdfs</artifactId> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> </dependency>
5.2、制作工具类
package com.jd.common.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); } }
5.3、配置文件
5.3.1、配置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.25.133: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
5.3.2、在applicationContext.xml中配置文件上传解析器
<!-- 为fastDFS上传文件配置附件解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="5242880"></property> //最大上传大小 <property name="defaultEncoding" value="UTF-8"></property> </bean>
5.4、后台上传代码
package com.jd.shop.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.jd.common.pojo.JdResult; import com.jd.common.utils.FastDFSClient; @RestController public class UploadController { @RequestMapping("/upload") public JdResult upload(MultipartFile file) { //1、读取上传文件名 String originalFilename = file.getOriginalFilename(); //2、获取到文件的扩展名(加1:只要扩展名,不要那个.) String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1); try { //3、创建fastdfs工具类对象 FastDFSClient fastDFSClient = new FastDFSClient("classpath:conf/fdfs_client.conf"); //4、执行上传 String path = fastDFSClient.uploadFile(file.getBytes(),extName); //5、将ip地址和文件所在url拼接起来 String url = "http://192.168.25.133/"+path; return new JdResult(true,"文件上传成功",url); }catch(Exception e) { return new JdResult(false,"文件上传失败",null); } } }
5.5、结合angularjs的前端代码
app.service("uploadService",function($http){ //文件上传 //angularJs对get或post请求的content-Type默认为application/json,通过设置headers:{‘content-Type‘:undefined} //这样浏览器就会自动帮我们设置content-Type 为multipart/form-data //data:formData 每一个数据都放入到formData //headers:{‘content-Type‘:undefined} 附件上传必须设置 //transformRequest:angular.identity 将表单里的数据进行二进制序列化 this.uploadFile = function(){ //创建一个表单数据对象 var formData = new FormData(); //向表单里添加文件,每次添加放在数组的第一个 formData.append("file",file.files[0]); return $http({ method:‘POST‘, url:‘../upload.do‘, data:formData, headers:{‘content-Type‘:undefined}, transformRequest:angular.identity }); } });
上传图片成功后就可以通过Storage返回的groupURL访问到该文件。
原文:https://www.cnblogs.com/709539062rao/p/13034925.html