使用Zuul上传文件
1.介绍
1.1: 对于小文件(1M以内上传),无须任何处理,即可正常上传。
1.2:对于大文件(10M以上)上传,需要为上传路径添加/zuul前缀。也可使用zuul.servlet-path自定义前缀。
假设zuul.routes.microservice-file-upload=/microservice-file-upload/**
如果http://{HOST}:{PORT}/upload是微服务microservice-file-upload的上传路径,则可使用Zuul的/zuul/microservice-file-upload/upload路径上传大文件。
1.3:如果Zuul使用了Ribbon做负载均衡,那么对于超大的文件(例如500M),需要提高超时设置,例如:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
2.实例
2.1:创建Maven工程,创建项目cloud-register-file-upload,并添加以下依赖:
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.boot
spring-boot-starter-actuator
2.2: 在启动类上添加@SpringBootApplication和@EnableEurekaClient
@EnableEurekaClient
@SpringBootApplication
public class RegisterFileUploadZuulApplication {
public static void main(String[] args) {
SpringApplication.run(RegisterFileUploadZuulApplication.class, args);
}
}
2.3:编写Controller
@RestController
public class FileUploadController {
/**
* 上传文件
* 测试方法:
* 有界面的测试:http://localhost:8024/index.html
* 使用命令:curl -F "file=@文件全名" localhost:8050/upload
* ps.该示例比较简单,没有做IO异常、文件大小、文件非空等处理
*
* @param file 待上传的文件
* @return 文件在服务器上的绝对路径
* @throws IOException IO异常
*/
@PostMapping("/upload")
String handleFileUpload(@RequestParam(value = "file", required = true) MultipartFile file) throws IOException {
byte[] bytes = file.getBytes();
File fileToSave = new File(file.getOriginalFilename());
FileCopyUtils.copy(bytes, fileToSave);
return fileToSave.getAbsolutePath();
}
}
2.4:配置application.yml
server:
port: 8024
spring:
application:
name: cloud-register-file-upload-zuul
http:
multipart:
max-file-size: 2000Mb # Max file size,默认1M
max-request-size: 2500Mb # Max request size,默认10M
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8001/eureka/
management:
security:
enabled: false
logging:
level:
com.netflix: DEBUG
2.5:启动
2.5.1:测试一
启动cloud-discovery-eureka微服务,port=8001;
启动cloud-register-file-upload微服务,port=8024
访问:http://localhost:8024/upload,发现上传小文件能上传成功
当我上传大文件时,报错java.lang.OutOfMemoryError: PermGen space
很容易知道是内存溢出, 配下内存就行了【-Xms128m -Xmx1024m -XX:MaxPermSize=512m 】。见下图,发现能上传成功。
2.5.2:测试二
在2.5.1的基础上,启动cloud-register-gateway-zuul微服务,port=8023
访问:http://localhost:8023/cloud-register-file-upload/upload,上传小文件发现上传成功
访问:http://localhost:8023/cloud-register-file-upload/upload,上传大文件,发现上传失败,需要增加zuul前缀,见下:
访问:http://localhost:8023/zuul/cloud-register-file-upload/upload,上传大文件,发现上传还是失败,需要添加配置,见下(2.5.3):
2.5.3:在cloud-register-gateway-zuul微服务application.yml配置中增加
在zuul微服务配置中添加本章开头所述的超时机制配置。gitee/github上传的代码把该配置注释了,本案例测试去掉注释即可。
继续访问http://localhost:8023/zuul/cloud-register-file-upload/upload即可。
2.5.4:特殊状况
本案例米兜按照官网配置了,依旧发现上传几十M的文件可以,大于几十M有问题,米兜也很纳闷,似乎觉得是配置不生效。
2.5.5: 针对以上异常,米兜找到了解决方法
异常:This results in a "Required request part 'file' is not present" in the service.
参考链接(貌似是这几天官方修复的):https://github.com/spring-cloud/spring-cloud-netflix/issues/2903
处理方法:
总项目cloud中 spring-cloud.version 为Edgware.RELEASE
创建新项目cloud-upload 升级 spring-cloud.version为 Edgware.SR5
cloud及cloud-upload源码获取路径:
1.gitee:https://gitee.com/StarskyBoy
2.github: https://github.com/StarskyBoy
更多spring cloud精彩内容,请关注博主公众号