文件上传 微服务版
初始架构设计
1.初始化父工程 muyun1
<dependencyManagement>
<dependencies>
<!-- 对项目依赖的版本进行管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<!-- 仅在编译期间该注解生效-->
</dependency>
</dependencies>
2.初始化文件资源服务
<dependencies>
<!-- springboot启动依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos服务注册发现,启动nacos时发现该服务-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--Nacos Config (配置中心)-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- sentinel流量防卫兵-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--Spring Boot 监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
3.创建yml文件(因为需要配置到nacos配置中心,使用使用bootstrap)
server:
port: 9000
spring:
application:
name: mu-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true #开启通过服务注册中心的serviceId创建路由
routes:
- id: route01
##uri: http://localhost:8081/
uri: lb://mu-provider # lb为服务前缀,不能随意写
predicates: ###匹配规则
- Path=/nacos/provider/echo/**
filters:
- StripPrefix=1 #转发之前去掉path中第一层路径,例如nacos
sentinel:
transport:
dashboard: localhost:8180 #Sentinel 控制台地址
port: 8719 #客户端监控API的端口
eager: true #取消Sentinel控制台懒加载,即项目启动即连接
4.构建项目的启动类
@SpringBootApplication
public class ResourceApp {
public static void main(String[] args) {
SpringApplication.run(ResourceApp.class,args);
}
}
5.post请求实现文件的上传/resource/upload
cotroller层代码
package com.jt.resource.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/resource/")
public class ResourceController {
//当了类的上面添加了@Slf4J就不用自己创建下面的日志对象了
// private static final Logger log=
// LoggerFactory.getLogger(ResourceController.class);
@Value("${jt.resource.path}")
private String resourcePath;//="d:/uploads/";
@Value("${jt.resource.host}")
private String resourceHost;//="http://localhost:8881/";
@PostMapping("/upload/")
public String uploadFile(MultipartFile uploadFile) throws IOException {
//1.创建文件存储目录(按时间创建-yyyy/MM/dd)
//1.1获取当前时间的一个目录
String dateDir = DateTimeFormatter.ofPattern("yyyy/MM/dd")
.format(LocalDate.now());
//1.2构建目录文件对象
File uploadFileDir=new File(resourcePath,dateDir);
if(!uploadFileDir.exists())uploadFileDir.mkdirs();
//2.给文件起个名字(尽量不重复)
//2.1获取原文件后缀
String originalFilename=uploadFile.getOriginalFilename();
String ext = originalFilename.substring(
originalFilename.lastIndexOf("."));
//2.2构建新的文件名
String newFilePrefix=UUID.randomUUID().toString();
String newFileName=newFilePrefix+ext;
//3.开始实现文件上传
//3.1构建新的文件对象,指向实际上传的文件最终地址
File file=new File(uploadFileDir,newFileName);
//3.2上传文件(向指定服务位置写文件数据)
uploadFile.transferTo(file);
String fileRealPath=resourceHost+dateDir+"/"+newFileName;
log.debug("fileRealPath {}",fileRealPath);
//后续可以将上传的文件信息写入到数据库?
return fileRealPath;
}
}
5.服务端的跨域请求
package org.mubai.controller.config;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsFilterConfig {
@Bean
public FilterRegistrationBean<CorsFilter> filterFilterRegistrationBean(){
//1.对此过滤器进行配置(跨域设置-url,method)
UrlBasedCorsConfigurationSource configSource=new UrlBasedCorsConfigurationSource();
CorsConfiguration config=new CorsConfiguration();
//允许哪种请求头跨域
config.addAllowedHeader("*");
//允许哪种方法类型跨域 get post delete put
config.addAllowedMethod("*");
// 允许哪些请求源(ip:port)跨域
config.addAllowedOrigin("*");
//是否允许携带cookie跨域
config.setAllowCredentials(true);
//2.注册过滤器并设置其优先级
configSource.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> fBean= new FilterRegistrationBean(new CorsFilter(configSource));
fBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return fBean;
}
}
客户端工程逻辑实现
1.在pom文件里面添加spring启动的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.构建项目的启动类
@SpringBootApplication
public class UiApp {
public static void main(String[] args) {
SpringApplication.run(UiApp.class, args);
}
}
3.创建文件上传的页面,在resource创建static文件夹,创建fileupload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上载演示</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<form id="fileForm" method="post" enctype="multipart/form-data" onsubmit="return doUpload()">
<div>
<label>上传文件
<input id="uploadFile" type="file" name="uploadFile">
</label>
</div>
<button type="submit">上传文件</button>
</form>
</body>
<script>
//jquery代码的表单提交事件
function doUpload(){
//获得用户选中的所有图片(获得数组)
let files=document.getElementById("uploadFile").files;
if(files.length>0){
//获得用户选中的唯一图片(从数组中取出)
let file=files[0];
//开始上传这个图片
//由于上传代码比较多,不想和这里其它代码干扰,所以定义一个方法调用
upload(file);
}
//阻止表单提交效果
return false;
};
// 将file上传到服务器的方法
function upload(file){
//定义一个表单
let form=new FormData();
//将文件添加到表单中
form.append("uploadFile",file);
//异步提交
let url="http://localhost:8881/resource/upload/";
axios.post(url,form)
.then(function (response){
alert("upload ok")
console.log(response.data);
})
.catch(function (e){//失败时执行catch代码块
console.log(e);
})
}
</script>
</html>
启动服务访问测试
第一步:启动nacos服务(在这里做服务的注册和配置管理)
第二步:启动mu-resource服务,此服务提供文件上传功能
第三步:启动mu-resource-ui服务,此服务为客户端工程,提供静态资源的访问.所有页面放到此工程中.
第四步:打开浏览器,访问sca-resource-ui工程下的文件上传
使用API网关进行文件的跨域调用以及限流
1.创建mu-resource-gateway的maven项目
添加nacos和网管的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.配置bootstrap.yml
server:
port: 9000
spring:
application:
name: sca-resource-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
config:
server-addr: localhost:8848
file-extension: yml
gateway:
discovery:
locator:
enabled: true
routes:
- id: router01
uri: lb://sca-resource
predicates:
- Path=/sca/resource/upload/**
filters:
- StripPrefix=1
3.创建启动类
package com.jt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ResourceApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceApplication.class,args);
}
}
4.配置网管的跨域
方式1:java代码
package com.jt.config;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
//@Configuration
public class CorsFilterConfig {
@Bean
public CorsWebFilter corsWebFilter(){
//1.构建基于url方式的跨域配置
UrlBasedCorsConfigurationSource source= new UrlBasedCorsConfigurationSource();
//2.进行跨域配置
CorsConfiguration config=new CorsConfiguration();
//2.1允许所有ip:port进行跨域
config.addAllowedOrigin("*");
//2.2允许所有请求头跨域
config.addAllowedHeader("*");
//2.3允许所有请求方式跨域:get,post,..
config.addAllowedMethod("*");
//2.4允许携带有效cookie进行跨域
config.setAllowCredentials(true);
source.registerCorsConfiguration("/**",config);
return new CorsWebFilter(source);
}
}
方式二
yml文件,添加动态刷新注解,直接使用
spring:
cloud:
gateway:
globalcors: #跨域配置
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedHeaders: "*"
allowedMethods: "*"
allowCredentials: true
5.修改前端的请求路径,将服务端的跨域注释