Составной post-запрос из Angular в Spring

#angular #spring #spring-boot

#angular #весна #spring-boot

Вопрос:

Я здесь пытаюсь опубликовать некоторые данные из приложения Angular в серверную часть spring boot, и, к сожалению, я застрял с непонятной ошибкой на целый день,

Это мой API

 @PostMapping("/add", consumes = ["multipart/form-data"])
fun addTeam(
    @RequestPart(name = "file") file: MultipartFile,
    @RequestPart(name = "body") team: Team
): ResponseEntity<*> {
    val imgUrl = filesStorageService.storeFile(file)

    val fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
        .path("/storage/downloadFile/")
        .path(imgUrl)
        .toUriString()


    val list = teamService.addTeam(team, fileDownloadUri)
    return ResponseEntity(list, list.status)
}
 

и вот вызов Angular API

 addTeam(team: Team, coverFile: File): Observable<boolean> {
return new Observable<boolean>(subscriber => {
  let formDate = new FormData();
  formDate.append('file', coverFile);
  formDate.append('body', JSON.stringify(team));
  this
    .client
    .post<ResponseWrapper<Boolean>>(environment.BASE_URL   this.ADD_TEAM, formDate, {
      headers: {'Content-Type': 'multipart/form-data'},
     })
......
 

итак, здесь я получил исключение, в котором говорится

 org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
 

итак, я нашел несколько решений, предлагающих установить тип содержимого angular undefined на, но это также не сработало
, тогда я удалил тип содержимого из вызова angular

но это дает мне еще одну ошибку

 2020-12-12 19:12:41.298  WARN 16892 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]
 

итак, я сделал приложение spring accepts application/octet-stream , но это приводит ,

 2020-12-12 19:14:39.775  WARN 16796 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundarykunWjFPmOyVdc8vn' not supported]
 

итак, кто-нибудь может мне помочь в этом?

Кроме того, я попробовал этот API с помощью postman, и он работает, когда я добавляю тип содержимого в multipart/form-data

Комментарии:

1. Почему вы добавляете это как часть FormData formDate.append('body', JSON.stringify(team)); ?

2. эта часть для отправки тела team в виде json, проблема в том, что все работает на postman! но не с angular

3. FormData предназначен только для содержимого файла. Вы не можете добавить к нему другое тело запроса , поэтому он завершается с ошибкой.

4. Насколько я видел, вы можете отправить только одно тело запроса из angular. Это подпись http.post : post(url: string, body: any, options?: RequestOptionsArgs) : Observable<Response> . Допускается несколько заголовков, но, как вы можете видеть, не несколько тел запроса.

5. значит, я не могу отправить запрос, как то, что я сделал с postman?

Ответ №1:

Может быть, вы можете попробовать это в своем приложении angular:

 formDate.append('file', coverFile);
formDate.append('body', new Blob([JSON.stringfy(team)], { type: 'text/plain' }));
 

И теперь, в вашей Spring, измените тип team на string :

 @PostMapping("/add", consumes = ["multipart/form-data"])
fun addTeam(
    @RequestPart(name = "file") file: MultipartFile,
    @RequestPart(name = "body") team: String
): ResponseEntity<*> {
 

Теперь, после того, как вы получите result из body , вы можете разобрать его в объект с помощью spring.

Ответ №2:

Недавно я столкнулся с этой проблемой, но с помощью NestJS на серверной части и добавления имени файла в качестве третьего параметра в append() функцию помогло.

 formDate.append('file', coverFile, '<FILE_NAME_HERE>');
 

Также я думаю, что вам не нужно явно указывать заголовок ‘Content-Type’, Angular обнаруживает и устанавливает его автоматически.

Ответ №3:

перепробовав множество решений, я наконец обнаружил, что если я хочу опубликовать много частей в angular, я должен включить тело значения json в виде большого двоичного объекта json с его типом, и нет необходимости указывать тип содержимого самого запроса

точно так же, как это ,

 formData.append('body', new Blob([JSON.stringify(team)], {
    type: 'application/json'
  }));