在Spring Cloud系列(二十六) Zuul过滤器详解(Finchley.RC2版本)提到了Zuul上传文件的问题。这里整理一下:
- 上传文件含有中文名,需要为上传路径添加 /zuul 前缀(当前版本貌似已经修复,不需要添加 /zuul 前缀也可以)
- 对于小文件(1M以内)上传无需任何处理,对于大文件(10M以上)上传,需要为上传路径添加 /zuul 前缀,也可以使用 zuul.servlet-path 自定义前缀
- 假设 zuul.routes.file-upload = /file-upload/**,如果 http://{HOST}:{PORT}/uoload 是微服务 file-upload 上传路径,则可以使用 Zuul 的 /zuul/file-upload/upload 路径上传大文件
- 如果 Zuul 使用 Ribbon 做负载均衡,那么对于超大文件(例如500M)需要提升超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
ribbon.ConnectTimeout=3000
ribbon.ReadTimeout= 60000
添加 /zuul 前缀是指需要使用ZuulServlet来实现文件上传。
示例
第一步,创建一个Maven项目用来测试上传,命名file-upload,并引入以下依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
第二步,创建应用主类Application。
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
第三步,创建UploadController。
@RestController
public class UploadController {
@PostMapping(name = "/file-upload")
public String handleFileUpLoad(@RequestParam(value = "file") MultipartFile file) throws IOException {
System.out.println(file.getSize());
byte[] bytes = file.getBytes();
File fileToSave = new File(file.getOriginalFilename());
FileCopyUtils.copy(bytes, fileToSave);
String path = fileToSave.getAbsolutePath();
System.out.println(path);
return path;
}
}
第四步,创建配置文件application.yml。
spring:
application:
name: file-upload
servlet:
multipart:
max-file-size: 2000Mb
max-request-size: 2500Mb
server:
port: 5555
eureka:
client:
service-url:
defaultZone: http://localhost:1111/eureka/ #指定服务注册中心位置
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
第五步,在API网关服务添加路由规则。
zuul:
routes:
upload:
path: /upload/**
serviceId: file-upload
测试
启动服务注册中心,即eureka-server-vFinchley.Rc2工程
启动服务提供者file-upload,即file-upload工程
启动Zuu的APIl网关服务api-gateway,即api-gateway-vFinchley.RC2工程
由于是POST请求,使用postman来测试。
先不通过API网关上传文件
上传小文件,文件大小44kb,成功
上传大文件,文件大小122MB,成功(除非发生堆错误等问题,可以通过这篇文章修改配置java上传文件时抛出java.lang.OutOfMemoryError: Java heap space)。
通过API网关服务上传文件
上传小文件,成功
上传大文件,失败
添加 /zuul 前缀重写上传,成功
如果你的文件太大,比如1G以上,可能会报以下错误
There was an unexpected error (type=Internal Server Error, status=500).
TIMEOUT
修改Zuul的超时配置重新上传就好了。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
ribbon.ConnectTimeout=3000
ribbon.ReadTimeout= 60000