![](/img/trans.png)
[英]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.