Angular: cómo publicar un file en el server al enviar el formulario

Tengo un formulario que se publica en mi back-end (Kotlin, Spring Web). Esa forma tenía algunas inputs de text y la publicación funcionó a la perfección. Pero cuando agregué una input de file, la publicación dejó de funcionar y me devolvió el siguiente error:

{status: 400, error: "Bad Request",…} error: "Bad Request" exception: "org.springframework.http.converter.HttpMessageNotReadableException" message: "Could not read document: No suitable constructor found for type [simple type, class com.test.InsertConfigCommand]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)↵ at [Source: java.io.PushbackInputStream@2cb43211; line: 1, column: 2]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.test.InsertConfigCommand]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)↵ at [Source: java.io.PushbackInputStream@2cb43211; line: 1, column: 2]" 

Aquí están los códigos de mi stack:

Ver:

 <form ng-submit="insert(config)"> <input type="text" ng-model="config.name"> <input type="text" ng-model="config.address"> <input type="file" ng-model="config.file"> <button type="submit">Save</button> </form> 

Controlador (front-end):

 $scope.insert = function (config) { $http.post('/config', config) .then(function (response) { $.snackbar({content: "Success!"}); }, $scope.showErrorMessage); }; 

Controlador (back-end):

 @RequestMapping(method = arrayOf(RequestMethod.POST)) fun insert(@RequestBody config: InsertConfigCommand) = service.save(config) 

InsertConfigCommand

 data class InsertConfigCommand ( val name : String = "", val address : String = "", val file : MultipartFile ) 

Intenté hacer la publicación de la siguiente manera, funciona, pero solo envía el file:

Controlador (front-end):

 $scope.insert = function (file) { var fd = new FormData(); fd.append('file', file); return $http.post('/config', fd, { transformRequest: angular.identity, headers: { 'Content-Type': undefined } }); }; 

Controlador (back-end):

 @RequestMapping(method = arrayOf(RequestMethod.POST)) fun insert(@RequestParam(value = "file", requinetworking = true) file: MultipartFile) = service.save(file) 

¿Qué debo cambiar para que funcione esta publicación? Deseo enviar el file de input en el mismo object que el nombre y la dirección.

Supongo que estás usando Jackson, ¿verdad?

El bytecode de classs de datos en Kotlin tiene un aspecto diferente al de un POJO normal (con el constructor pnetworkingeterminado) y, por lo tanto, Jackson no puede inicializar dicha class. Intente agregar una dependencia al Módulo Jackson Kotlin y asegúrese de registrarlo.

Si usa Spring Boot, agregue el siguiente código a cualquiera de sus classs anotadas @Configuration:

 @Bean open fun kotlinModule(): KotlinModule { return KotlinModule() } 

y ver si ayuda.

He utilizado este tutorial que encapsula el file dentro del object FormData, y publica ese object https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs

 $scope.insert = function (config) { var fd = new FormData(); fd.append('name', config.name); fd.append('address', config.address); fd.append('file', $scope.file); $http.post('/config', fd, { transformRequest: angular.identity, headers: {'Content-Type': undefined} }) .then(function (response) { $.snackbar({content: "Success!"}); }, $scope.showErrorMessage); }; 

Y en mi controller Kotlin, recibo cada atributo como un param separado:

 @RequestMapping(method = arrayOf(RequestMethod.POST)) fun insert(@RequestParam(value = "name", requinetworking = true) name: String, @RequestParam(value = "address", requinetworking = true) address: String, @RequestParam(value = "file", requinetworking = false) file: MultipartFile): InsertConfigCommand? { val command = InsertConfigCommand( name = name, address = address, file = file) return service.save(command) }