I am trying to send a multipart request to the server but i am getting the following exception
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:188)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:104)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
Basing on tutorials and stackoverflow questions i have developped the folowing code
Controller
@RequestMapping(value = "/upload-file", method = RequestMethod.POST)
public ResponseEntity<Void> getUploadFile(@RequestParam("file") MultipartFile file) {
LOGGER.debug(String.valueOf(file));}
MultipartConfiguration
@Configuration
@EnableWebMvc
public class MultipartConfiguration {
private static final String DEFAULT_ENCODING = "UTF-8";
private static final long MAX_UPLOAD_FILE_SIZE = 100000000;
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver resolver=new CommonsMultipartResolver();
resolver.setDefaultEncoding("utf-8");
resolver.setMaxUploadSize(MAX_UPLOAD_FILE_SIZE);
resolver.setDefaultEncoding(DEFAULT_ENCODING);
return resolver;
}
}
html
<input type="file" style="display:none" #fileupload name="image" (change)="fileProgress($event)" />
Component
export class FileUploadComponent {
fileData: any = null;
uploadedFilePath: string = null;
formData = new FormData();
reader = new FileReader();
@Output() fiLoaded: EventEmitter<File> = new EventEmitter();
constructor(private pointeService: PointeService) { }
fileProgress(fileInput: any) {
this.fileData = fileInput.target.files[0];
this.reader.readAsDataURL(this.fileData);
this.reader.onloadend = (_event) => {
this.formData.append('file', this.fileData);
this.onFileLoaded(this.formData);
};
}
onFileLoaded(formData: any) {
this.pointeService.postModifiedFileExel(formData)
.subscribe(events => {
if (events.type === HttpEventType.UploadProgress) {
} else if (events.type === HttpEventType.Response) {
// this.fileUploadProgress = 0;
console.log(events.body);
alert('SUCCESS !!');
}
});
}
}
Service
postModifiedFileExel(formData: any) {
return this.http.post(`${AppUtils.REST_API_SERVER}/espacegroupe/upload-file`, formData , {
reportProgress: true,
observe: 'events'
});
}
I also noticed that my post contains just the name of the file and it does not cotains data in byte format
Any suggestions please?
For those who still stuck in the same issue, i will first explain how i debugged to find out the solution, and second what i was doing wrong.
Debugging
When i flowed the stack trace i found two methods that are responsible for the message that i receive i.e Current request is not a multipart request
public class ServletFileUpload extends FileUpload {
private static final String POST_METHOD = "POST";
public static final boolean isMultipartContent(HttpServletRequest request) {
return !"POST".equalsIgnoreCase(request.getMethod()) ? false : FileUploadBase.isMultipartContent(new ServletRequestContext(request));
}
.....
}
and
public abstract class FileUploadBase {
public FileUploadBase() {
}
public static final boolean isMultipartContent(RequestContext ctx) {
String contentType = ctx.getContentType();
if (contentType == null) {
return false;
} else {
return contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/");
}
}
....
}
This means that if your call is different of POST
or your content type does not start with "multipart/"
your playload is considered as a non multipart
and i noticed that my content Type was alway Content-Type: application/json
But why do i always have Content-Type: application/json
althought formData is supposed to be Content-Type: multipart/form-data
?
In my case it was because in the application there is an url interceptor that always sets in the header Content-Type: application/json
.
const authReq = req.clone({setHeaders: {'Content-Type': 'application/json'}, withCredentials: true});
To be sure that you send the right data type, be sure that in request Header you have
Content-Type: multipart/form-data;boundary=...
and that your formData is in binary.
Here there is a link to the article that helped me to resolve this issue