畅购学习 第二天
1、CORS解决跨域问题
什么是跨域
同源策略是一种约定,他是浏览器最核心也是最基本的安全功能,如果缺少 了同源策略,则浏览器的正常功能可能都会受到影响。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。
同源就是两个页面具有相同的协议,主机和端口号
只有发生ajax请求,才可能出现跨域情况
CORS是W3C标准,全称 跨域资源共享。CORS需要浏览器和服务器同时支持,目前所有浏览器都支持该功能 服务器中springMVC在4.2或以上版本。可以使用注解实现跨域,Controller雷伤添加注解@CrossOrigin
2、分布式文件存储系统 FastDFS
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称为存储服务器。
上传流程
- Storage server 定时获取Storage 的信息,然后将Storage 的状态信息发送给Tracker server (那台机子负载轻啊,容量高啊)
- 客户端发送一个上传请求给Tracker
- Tracker接受请求,并查询可用的Storage
- 讲Storage的信息返回给客户端,包括Storage的端口以及 ip
- 客户端上传文件(file content 和 metadata),发送给Storage
- Storage将会生成文件ID 并将文件写到磁盘,然后将file_id(路径信息和文件名)返回给客户端
- 客户端存储信息
文件服务器的搭建
1.导入依赖
1 <dependencies> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-web</artifactId> 5 </dependency> 6 <dependency> 7 <groupId>net.oschina.zcx7878</groupId> 8 <artifactId>fastdfs-client-java</artifactId> 9 <version>1.27.0.0</version> 10 </dependency> 11 <dependency> 12 <groupId>com.changgou</groupId> 13 <artifactId>changgou_common</artifactId> 14 <version>1.0-SNAPSHOT</version> 15 </dependency> 16 </dependencies>
2.配置文件的配置
fdfs_client.conf
1 connect_timeout = 60 #连接超时时间 单位秒 2 network_timeout = 60 #通信超时时间单位时间 3 charset = UTF-8 4 http.tracker_http_port = 8080 #trancker服务器i端口和ip 5 tracker_server = 192.168.200.128:22122
application.yml
1 spring: 2 servlet: 3 multipart: 4 max-file-size: 10MB # 单个文件大小 5 max-request-size: 10MB # 设置总上传的数据大小 6 server: 7 port: 9008 8 eureka: 9 client: 10 service-url: 11 defaultZone: http://127.0.0.1:6868/eureka 12 instance: 13 prefer-ip-address: true 14 feign: 15 hystrix: 16 enabled: true
3.文件信息封装
1 public class FastDFSFile { 2 //文件名字 3 private String name; 4 //文件内容 5 private byte[] content; 6 //文件扩展名 7 private String ext; 8 //文件MD5摘要值 9 private String md5; 10 //文件创建作者 11 private String author; 12 13 public FastDFSFile(String name, byte[] content, String ext, String height, 14 String width, String author) { 15 super(); 16 this.name = name; 17 this.content = content; 18 this.ext = ext; 19 this.author = author; 20 } 21 22 public FastDFSFile(String name, byte[] content, String ext) { 23 super(); 24 this.name = name; 25 this.content = content; 26 this.ext = ext; 27 } 28 29 public String getName() { 30 return name; 31 } 32 33 public void setName(String name) { 34 this.name = name; 35 } 36 37 public byte[] getContent() { 38 return content; 39 } 40 41 public void setContent(byte[] content) { 42 this.content = content; 43 } 44 45 public String getExt() { 46 return ext; 47 } 48 49 public void setExt(String ext) { 50 this.ext = ext; 51 } 52 53 public String getMd5() { 54 return md5; 55 } 56 57 public void setMd5(String md5) { 58 this.md5 = md5; 59 } 60 61 public String getAuthor() { 62 return author; 63 } 64 65 public void setAuthor(String author) { 66 this.author = author; 67 } 68 }
4.创建FastDFSClient类,实现FastDFS信息获取以及文件的相关操作
1 public class FastDFSClient { 2 3 private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class); 4 5 /*** 6 * 初始化加载FastDFS的TrackerServer配置 7 */ 8 static { 9 try { 10 String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath(); 11 ClientGlobal.init(filePath); 12 } catch (Exception e) { 13 logger.error("FastDFS Client Init Fail!",e); 14 } 15 } 16 17 /*** 18 * 文件上传 19 * @param file 20 * @return 1.文件的组名 2.文件的路径信息 21 */ 22 public static String[] upload(FastDFSFile file) { 23 //获取文件的作者 24 NameValuePair[] meta_list = new NameValuePair[1]; 25 meta_list[0] = new NameValuePair("author", file.getAuthor()); 26 27 //接收返回数据 28 String[] uploadResults = null; 29 StorageClient storageClient=null; 30 try { 31 //创建StorageClient客户端对象 32 storageClient = getTrackerClient(); 33 34 /*** 35 * 文件上传 36 * 1)文件字节数组 37 * 2)文件扩展名 38 * 3)文件作者 39 */ 40 uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list); 41 } catch (Exception e) { 42 logger.error("Exception when uploadind the file:" + file.getName(), e); 43 } 44 45 if (uploadResults == null && storageClient!=null) { 46 logger.error("upload file fail, error code:" + storageClient.getErrorCode()); 47 } 48 //获取组名 49 String groupName = uploadResults[0]; 50 //获取文件存储路径 51 String remoteFileName = uploadResults[1]; 52 return uploadResults; 53 } 54 55 /*** 56 * 获取文件信息 57 * @param groupName:组名 58 * @param remoteFileName:文件存储完整名 59 * @return 60 */ 61 public static FileInfo getFile(String groupName, String remoteFileName) { 62 try { 63 StorageClient storageClient = getTrackerClient(); 64 return storageClient.get_file_info(groupName, remoteFileName); 65 } catch (Exception e) { 66 logger.error("Exception: Get File from Fast DFS failed", e); 67 } 68 return null; 69 } 70 71 /*** 72 * 文件下载 73 * @param groupName 74 * @param remoteFileName 75 * @return 76 */ 77 public static InputStream downFile(String groupName, String remoteFileName) { 78 try { 79 //创建StorageClient 80 StorageClient storageClient = getTrackerClient(); 81 82 //下载文件 83 byte[] fileByte = storageClient.download_file(groupName, remoteFileName); 84 InputStream ins = new ByteArrayInputStream(fileByte); 85 return ins; 86 } catch (Exception e) { 87 logger.error("Exception: Get File from Fast DFS failed", e); 88 } 89 return null; 90 } 91 92 /*** 93 * 文件删除 94 * @param groupName 95 * @param remoteFileName 96 * @throws Exception 97 */ 98 public static void deleteFile(String groupName, String remoteFileName) 99 throws Exception { 100 //创建StorageClient 101 StorageClient storageClient = getTrackerClient(); 102 103 //删除文件 104 int i = storageClient.delete_file(groupName, remoteFileName); 105 } 106 107 /*** 108 * 获取Storage组 109 * @param groupName 110 * @return 111 * @throws IOException 112 */ 113 public static StorageServer[] getStoreStorages(String groupName) 114 throws IOException { 115 //创建TrackerClient 116 TrackerClient trackerClient = new TrackerClient(); 117 //获取TrackerServer 118 TrackerServer trackerServer = trackerClient.getConnection(); 119 //获取Storage组 120 return trackerClient.getStoreStorages(trackerServer, groupName); 121 } 122 123 /*** 124 * 获取Storage信息,IP和端口 125 * @param groupName 126 * @param remoteFileName 127 * @return 128 * @throws IOException 129 */ 130 public static ServerInfo[] getFetchStorages(String groupName, 131 String remoteFileName) throws IOException { 132 TrackerClient trackerClient = new TrackerClient(); 133 TrackerServer trackerServer = trackerClient.getConnection(); 134 return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName); 135 } 136 137 /*** 138 * 获取Tracker服务地址 139 * @return 140 * @throws IOException 141 */ 142 public static String getTrackerUrl() throws IOException { 143 return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/"; 144 } 145 146 /*** 147 * 获取Storage客户端 148 * @return 149 * @throws IOException 150 */ 151 private static StorageClient getTrackerClient() throws IOException { 152 TrackerServer trackerServer = getTrackerServer(); 153 StorageClient storageClient = new StorageClient(trackerServer, null); 154 return storageClient; 155 } 156 157 /*** 158 * 获取Tracker 159 * @return 160 * @throws IOException 161 */ 162 private static TrackerServer getTrackerServer() throws IOException { 163 TrackerClient trackerClient = new TrackerClient(); 164 TrackerServer trackerServer = trackerClient.getConnection(); 165 return trackerServer; 166 } 167 }
5.创建一个FileController,在该控制器中实现文件上传操作
1 @RestController 2 @RequestMapping("/file") 3 public class FileController { 4 5 @PostMapping("/upload") 6 public Result uploadFile(MultipartFile file){ 7 try{ 8 //判断文件是否存在 9 if (file == null){ 10 throw new RuntimeException("文件不存在"); 11 } 12 //获取文件的完整名称 13 String originalFilename = file.getOriginalFilename(); 14 if (StringUtils.isEmpty(originalFilename)){ 15 throw new RuntimeException("文件不存在"); 16 } 17 18 //获取文件的扩展名称 abc.jpg jpg 19 String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); 20 21 //获取文件内容 22 byte[] content = file.getBytes(); 23 24 //创建文件上传的封装实体类 25 FastDFSFile fastDFSFile = new FastDFSFile(originalFilename,content,extName); 26 27 //基于工具类进行文件上传,并接受返回参数 String[] 28 String[] uploadResult = FastDFSClient.upload(fastDFSFile); 29 30 //封装返回结果 31 String url = FastDFSClient.getTrackerUrl()+uploadResult[0]+"/"+uploadResult[1]; 32 return new Result(true,StatusCode.OK,"文件上传成功",url); 33 }catch (Exception e){ 34 e.printStackTrace(); 35 } 36 return new Result(false, StatusCode.ERROR,"文件上传失败"); 37 } 38 }