I have an Java application running Spring and on it I have an endpoint to receive multiple files but, every time I hit it I get "415 Status".
This is my endpoint:
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public List<Media> uploadMediaToS3(@RequestPart("files") Set<MultipartFile> files,
@RequestPart("mediaUploads") Set<MediaUploadDTO> mediaUploadDTOs,
@RequestParam("profileId") UUID profileId) throws IOException, FindMeDataNotFoundException {
logger.info("WORKED! " + profileId.toString());
return new ArrayList<>();
}
And this is how I'm building the request on my Angular application:
PS: postMedia
is an array of { fileData: fileToSend, base64: event.target!.result!.toString() }
.
let formDataWithFiles = new FormData();
let filesRaw = [] as Array<File>;
let filesInfo = [] as Array<Media>;
this.postMedias.forEach(postMedia => {
filesRaw.push(new File([postMedia.base64], postMedia.fileData.fileName));
filesInfo.push(postMedia.fileData);
});
formDataWithFiles.append('files', new Blob(filesRaw));
formDataWithFiles.append('mediaUploads', JSON.stringify(filesInfo));
console.log(formDataWithFiles);
this.postService.uploadMedias(formDataWithFiles, this.profileId);
The service call is:
uploadMedias(files: FormData, profileId: string) {
return firstValueFrom(this.appService.POST<Media>(`medias/upload?profileId=${profileId}`, files)).then(savedMedia => {
return savedMedia;
}, error => {
throw error;
});
} My files are being upload to my Angular application by an Input type file and are being save onto a variable by using this code:
if (file.target.files[0]['size'] / 1e+6 == this.maxMediaSize) {
this.openSnackBar(this.translateService.instant('CUSTOM-FILE-INPUT.MAX-SIZE-ERROR') + `${this.maxMediaSize}Mb`, 2500);
} else {
let reader = new FileReader();
reader.readAsDataURL(file.target.files[0]);
let fileToSend: Media = {} as Media;
fileToSend.mediaExtension = file.target.files[0].type.substring(file.target.files[0].type.indexOf('/') + 1).toUpperCase();
fileToSend.mediaPrivacy = 'PUBLIC';
fileToSend.mediaPrice = 0.0
fileToSend.whenToDelete = new Date().getTime();
fileToSend.fileName = file.target.files[0].name;
fileToSend.mediaType = 'PROFILE_AVATAR_MEDIA';
reader.onload = (event) => {
this.formFiles.push({ fileData: fileToSend, base64: event.target!.result!.toString() });
};
}
I tried using Postman to test this endpoint but, getting nowhere either:
I have another endpoint that saves a single file and it works perfectly:
@PostMapping(value = "/update-avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Media uploadAvatarToS3(@RequestPart("avatar") MultipartFile avatar,
@RequestPart("mediaUpload") MediaUploadDTO mediaUploadDTO,
@RequestParam("profileId") UUID profileId) throws IOException, FindMeDataNotFoundException {
return mediaService.uploadAvatar(avatar, profileId, mediaUploadDTO);
}
My application.properties has the "multipart" properties in it:
spring.servlet.multipart.enabled=true
spring.servlet.multipart.location=${java.io.tmpdir}
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
My Spring version is 3.3.3 with Java 17
If anyone has any idea on what I could try, it'd help a lot! Thanks in advance!
Got it working by making some changes:
On my Back end, I had to change the Set<MultipartFile> medias
to MultipartFile[] medias
, then it was able to give me more than just a 415 code.
After that, I changed the front-end to this:
this.postMedias.forEach(postMedia => {
formDataWithFiles.append('medias', new File([base64ToFile(postMedia.base64)], postMedia.fileData.fileName));
filesInfo.push(postMedia.fileData);
});
formDataWithFiles.append('mediaUploads', new Blob([JSON.stringify(filesInfo)], { type: 'application/json' }));
this.postService.uploadMedias(formDataWithFiles, this.cookieService.get('ProfileId'), result.id).then(result => {
this.loadPosts();
});
I forgot to actually parse the Base64 to file using base64ToFile
, after that it worked perfectly.