Issue
I am trying to upload Angular form data to Spring Boot server.
Simply, in Spring Boot I accept:
data class Photo(
val id: Long = 0L,
val file: MultipartFile
)
data class PostRequest(
@field:Size(min = 1, max = 100)
val title: String,
val photos: List<Photo> = mutableListOf()
)
via Controller:
fun createPost(@Valid @ModelAttribute postRequest: PostRequest)
In Angular I created this form:
this.postForm = this.fb.group({
title: ["", [Validators.required, Validators.minLength(1)]],
photos: this.fb.array([]),
});
When user uploads a photo I call these lines:
const photosArray = this.postForm.get("photos") as FormArray;
const newPhotoGroup = this.fb.group({
id: "",
file: event.target.result,
});
photosArray.push(newPhotoGroup);
Finally, I construct a form data object:
const formData = new FormData();
formData.append("title", this.postForm.get("title")?.value);
formData.append("photos", this.postForm.get("photos")?.value);
I use this function to post this form to API:
postRequest<T>(url: string, body: any): Observable<HttpResponse<T>> {
const headers = new HttpHeaders({
"Content-Type": "multipart/form-data",
});
return this.http.post<T>(url, body, {
headers,
observe: "response",
withCredentials: true,
});
}
In developer tools I see this request:
Spring Boot complains:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Someone, enlighten me. Thank you.
Solution
photos
form control is an array of objects, which is sent like that (as [object Object]
) in the request, hence the error.
You need to loop the array and append each file:
const formData = new FormData();
formData.append("title", this.postForm.get("title")?.value);
// loop files and append them
this.postForm.get("photos")?.value.forEach((obj:any, i:number)=>{
formData.append("photos", obj.file); // user property which has file:File
});
Also, when adding file to the array, make sure it has File
type (event.target.result
seems to be a string now, if so, use event.target.file
or add a new property, for example 'uploadFile', and add that to formData
later):
const newPhotoGroup = this.fb.group({
id: "",
file: event.target.result, // this should be File from event.target.file
});
if you want to include id
, i.e. custom file data, along with the file, it cannot go along with the file in the same formData key
You could use id instead of filename:
formData.append("photos", obj.file, obj.id)
or adapt the upload process something like this: sending JSON object along with file using FormData in ajax call and accessing the json object in PHP
Finally, make the reqeuest without content-type headers
, the FormData
will handle it:
return this.http.post<T>(url, body, {
observe: "response",
withCredentials: true,
});
Answered By - traynor
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.