[英]org.springframework.web.multipart.MultipartException: Current request is not a multipart request spring boot
[英]Spring Boot + Angular - MultipartException: Current request is not a multipart request
我在将 Angular 9 与 Spring Boot 一起用于一个简单的应用程序时遇到问题,该应用程序在同一请求中上传文件以及来自 UI 的数据。 在我使用基本身份验证实现安全之前,一切正常。 现在,在我登录并想要上传数据后,我收到以下错误:
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
将标头设置为Content-Type: 'multipart/form-data'
和使用 MultipartFile 的 Spring Controller。 奇怪的是 GET 请求运行良好,除了它的内容类型是application/json
。 如果我禁用了 http-interceptor,则错误变为Access to XMLHttpRequest at 'http://localhost:8080/pacients' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
。 我还尝试了所有处理 Angular 和 Spring 相关的 CORS 的解决方法,但没有成功。
用于上传文件的 Angular 组件:
pacient: Pacient;
pacientForm: FormGroup = new PacientCreateFormBuilder().build();
submitPromise: Promise<Pacient>;
onSubmit() {
if(this.pacientForm.valid) {
const formData: FormData = new FormData();
formData.append('pacientFile', <File>this.pacientForm.value.pacientFile);
formData.append('newPacient', new Blob([JSON.stringify(this.pacientForm.value)], {type: "application/json"}));
this.submitPromise = this.pacientCreateService.save(formData);
} else {
ValidationUtils.markFormAsDirty(this.pacientForm);
}
}
用于上传的 Angular 服务:
public save(formData: FormData) {
var headers = new HttpHeaders(
{
'Content-Type': 'multipart/form-data',
'Authorization': `Basic ${window.btoa(this.authService.username + ":" + this.authService.password)}`
}
);
return this.httpClient.post<Pacient>("http://localhost:8080/pacient", formData, {headers: headers})
.toPromise();
}
角度认证服务:
authenticate(username: String, password: String) {
return this.http.get(`http://localhost:8080/auth`, {
headers: { authorization: this.createBasicAuthToken(username, password) }}).pipe(map((res) => {
this.username = username;
this.password = password;
this.registerInSession(username, password);
}));
}
createBasicAuthToken(username: String, password: String) {
return 'Basic ' + window.btoa(username + ":" + password);
}
registerInSession(username, password) {
sessionStorage.setItem(this.SESSION_KEY, username);
}
角http拦截器:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.isUserLoggedin() && req.url.indexOf('basicauth') === -1) {
const request = req.clone({
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Basic ${window.btoa(this.authService.username + ":" + this.authService.password)}`
})
});
return next.handle(request);
}
return next.handle(req);
}
弹簧安全配置:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = new StandardPasswordEncoder();
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER")
.and()
.withUser("admin")
.password("admin")
.roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().
disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
弹簧控制器:
@PostMapping("/pacient")
public Pacient create(@RequestPart("pacientFile") MultipartFile pacientFile, @RequestPart("newPacient") PacientDTO pacientDTO)
编辑:如果我在控制器中使用@PostMapping(value = "/pacient", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
,则错误正在发生变化,并且仅出现在浏览器的控制台和 sais
从源“ http://localhost:4200 ”访问“ http://localhost:8080/pacient ”的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头.
为了克服它,我用@CrossOrigin(origins = {"http://localhost:4200"})
更新了控制器,将以下字段添加到服务的标题中
'Access-Control-Allow-Headers': `Content-Type`,
'Access-Control-Allow-Methods': `POST`,
'Access-Control-Allow-Origin': `*`
并且还创建了一个 proxy.conf.json 文件
{
"/": {
"target": "http://localhost:8080",
"secure": false
}
}
并将其添加到 package.json,以"start": "ng serve --proxy-config proxy.conf.json"
并在我的 Spring Security 配置类中添加 CORS 配置
@Bean
CorsConfigurationSource corsConfigurationSource()
{
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
但仍然没有运气...
我自己也遇到了这个问题,这对我来说是一个非常愚蠢的错误,但我想我应该分享一下,以防有人犯同样的错误。 我刚刚将文件移到了我的虚拟机上,而我的用户帐户无权访问该文件……一旦我更改了文件的权限,它就按预期工作了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.