Невозможно отправить запрос POST, который содержит объект (внешний ключ) с Angular 5, чтобы оставить бэкэнд на основе Spring Boot

У меня есть Status Code 400 в интерфейсе, когда я пытаюсь отправить запрос POST с Angular 5 на Spring Boot Rest Controller.

Вот сущность:

@Entity
public class Prestataires implements Serializable 
{
@Id @GeneratedValue
private Long id;
private String nom;
private String email;
private String tele;
private String fax;
private String rib;
private String adresse;
private String taches;
private String photo;

@Lob
private byte[] file;

 @ManyToOne
 @JoinColumn(name = "ID_PRESTATAIRES_TYPES")
 private PrestatairesTypes prestatairesTypes;

//--------------Getters and Setters------------------------
//--------------Constructors-------------------------------

}

Вот вторая сущность:

@Entity
public class PrestatairesTypes implements Serializable 
{
 @Id @GeneratedValue
 private Long id;

 private String designation;

 //-------------------Constructors----------------
 //--------------Getters and Setters-------------------

 //---------------------OneToMany---------------------

 @OneToMany(mappedBy = "prestatairesTypes")
 private Collection<Prestataires> prestataires; 

 }

Вот RestController:

 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;

 import smart.syndic.dao.PrestatairesRepository;
 import smart.syndic.entities.Prestataires;

 @RestController
 @CrossOrigin("*")
 public class PrestatairesRestController 
 {
  @Autowired
  private PrestatairesRepository repository;

 @RequestMapping(value = "/prestataires", 
        method=RequestMethod.POST)
 public Prestataires addVilles(Prestataires p,
        @RequestParam("multipartFile") MultipartFile file)
 {
    byte[] rawFile = null;
    try{

        rawFile = file.getBytes();
    }catch(Exception e){
        e.printStackTrace();
    }

    p.setFile(rawFile);

    return repository.save(p);              
 }

 }

Вот предварительные образцы моделей в TypeScript:

 export class PrestatairesModel
 {
  id:any;
  nom:any;
  email:any;
  tele:any;
  fax:any;
  rib:any;
  adresse:any;
  taches:any;
  photo:any;
  file:any;

  prestatairesTypes:any;

  }

Вот модель PrestatairesTypes в TypeScript:

export class PrestatairesTypeModel
{
 id:any;
 designation:any;
}

Вот угловой контроллер в TypeScript:

 import { Component, OnInit } from '@angular/core';
 import {PrestatairesService} from "../../services/prestataires.service";
 import {PrestatairesTypeModel} from "../../modeles/prestatairesType.model";
 import {PrestatairesModel} from "../../modeles/prestataires.model";


 @Component({
 selector: 'app-ajouter-prestataires',
 templateUrl: './ajouter-prestataires.component.html',
 styleUrls: ['./ajouter-prestataires.component.css']
 })
 export class AjouterPrestatairesComponent implements OnInit {

 nom:any = null;
 email:any = null;
 tele:any = null;
 fax:any = null;
 rib:any = null;
 adresse:any = null;
 taches:any = null;
 photo:any = null;

 selectTypes:any;

 typePrestataire:any;

 tousLesPrestatairesTypes:any;

 modelType:any;

 imageURL:string = "../assets/images/MeG.jpg";

 fileToUpload:File = null;

  modelPrestataires:any;


  constructor(private service:PrestatairesService) { }

  ngOnInit()
  {
     this.getAllTypes();

  }

  handleFileInput(file:any)
  {
    this.fileToUpload = <File>file.target.files[0];
    let reader = new FileReader();
    reader.onload = (event:any)=>{
    this.imageURL = event.target.result;
  }

  reader.readAsDataURL(this.fileToUpload);

  }

  getAllTypes()
  {
    this.service.getAllTypes()
    .subscribe(data=>{
      this.tousLesPrestatairesTypes = data;
    }, err=>{

    }, ()=>{

    })
 }

  ajouterTypesPrestataires()
 {
   this.modelType = new PrestatairesTypeModel();
   this.modelType.designation = this.typePrestataire;

   this.service.ajouterType(this.modelType)
    .subscribe(data=>{

    console.info("Added");
    this.getAllTypes();
    this.modelType = data;

   }, err=>{
    console.info("Error");
  }, ()=>{

  })

}

 ajouterPrestataires()
 {

  this.modelPrestataires = new PrestatairesModel();
  this.modelPrestataires.nom = this.nom;
  this.modelPrestataires.email = this.email;
  this.modelPrestataires.tele = this.tele;
  this.modelPrestataires.fax = this.fax;
  this.modelPrestataires.rib = this.rib;
  this.modelPrestataires.adresse = this.adresse;
  this.modelPrestataires.taches = this.taches;
  this.modelPrestataires.photo = this.photo;
  this.modelPrestataires.file = this.fileToUpload;

  this.service.getOneType(this.selectTypes)
    .subscribe(data=>{
      this.modelPrestataires.prestatairesTypes = data;
    }, err=>{

    }, ()=>{
      this.service.uploadFile(this.modelPrestataires)
        .subscribe(data=>{

          this.modelPrestataires = data;

        }, err=>{

        }, ()=>{

        });
    });




   }

 getOneType(id:any)
 {
   this.service.getOneType(id)
    .subscribe(data=>{
    this.modelType = data;
  }, err=>{

  }, ()=>{

  });

 }

 }

Вот вид:

<div class = "right_col" role = "main">
 <div class = "">
  <div class = "page-title">
    <div class = "title_left">
    <h3>Ajouter Prestataires</h3>
  </div>


  </div>
<div class = "clearfix"></div>

<div class = "row">
  <div class = "col-md-12 col-sm-12 col-xs-12">
    <div class = "x_panel">
      <div class = "x_title">
        <h2>Nouveau Prestataire</h2>
        <ul class = "nav navbar-right panel_toolbox">
          <li><a class = "collapse-link"><i class = "fa fa-chevron-up"></i></a>
          </li>
          <li class = "dropdown">
            <a href = "#" class = "dropdown-toggle" data-toggle = "dropdown" 
  role = "button" aria-expanded = "false"><i class = "fa fa-wrench"></i></a>
            <ul class = "dropdown-menu" role = "menu">
              <li><a routerLink = "/prestataires">Retour Prestataires</a>
              </li>
            </ul>
          </li>
          <li><a class = "close-link"><i class = "fa fa-close"></i></a>
          </li>
        </ul>
        <div class = "clearfix"></div>
      </div>
      <div class = "x_content">

        <div class = "x_content">




            <div id = "containerAjouterPrestataires">

            </div>

            <form class = "form-horizontal form-label-left">

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
        12">Raison Social/Nom<span class = "required">*</span>
                </label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <input [(ngModel)] = "nom" name = "nom" type = "text" required 
 class = "form-control col-md-7 col-xs-12">
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
  12">Email<span class = "required">*</span>
                </label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <input [(ngModel)] = "email" name = "email" type = "email" 
  required class = "form-control col-md-7 col-xs-12">
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
        12">Téléphone<span class = "required">*</span></label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <input [(ngModel)] = "tele" name = "tele" class = "form-control 
      col-md-7 col-xs-12" type = "text" required>
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
    12">Fax<span class = "required">*</span></label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <input [(ngModel)] = "fax" name = "fax" class = "form-control 
     col-md-7 col-xs-12" type = "text" required>
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
   12">RIB<span class = "required">*</span></label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <input [(ngModel)] = "rib" name = "rib" class = "form-control 
     col-md-7 col-xs-12" type = "text" required>
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
   12">Type<span class = "required">*</span></label>
                <div class = "col-md-6 col-sm-6 col-xs-12">

                  <div class = "input-group">
                    <select class = "form-control" name = "selectTypes" 
 [(ngModel)] = "selectTypes">
                      <option selected = "selected" *ngFor = "let s of 
  tousLesPrestatairesTypes" [value] = "s.id" >
                        {{s.designation}}
                      </option>
                    </select>
                    <span class = "input-group-btn">
                    <!-- Button trigger modal -->
                    <button type = "button" class = "btn btn-default" data- 
  toggle = "modal" data-target = "#myModal">
                      Ajouter Type
                    </button>
                  </span>
                  </div>
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
 12">Adresse<span class = "required">*</span>
                </label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <textarea [(ngModel)] = "adresse" name = "adresse" 
 class = "form-control" rows = "3" placeholder = "Adresse"></textarea>
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
 12">Tâches<span class = "required">*</span>
                </label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <textarea [(ngModel)] = "taches" name = "taches" class = "form- 
  control" rows = "3" placeholder = "Tâches"></textarea>
                </div>
              </div>

              <!-- Modal -->
              <div class = "modal fade" id = "myModal" tabindex = "-1" 
  role = "dialog" aria-labelledby = "myModalLabel">
                <div class = "modal-dialog modal-lg" role = "document">
                  <div class = "modal-content">
                    <div class = "modal-header">
                      <button type = "button" class = "close" data- 
  dismiss = "modal" aria-label = "Close"><span aria-hidden = "true">&times;</span> 
  </button>
                      <h4 class = "modal-title" id = "myModalLabel">Ajouter Type 
   Prestataire</h4>
                    </div>
                    <div class = "modal-body">
                      <form class = "form-horizontal form-label-left">

                        <div id = "containerType">

                        </div>

                        <div class = "form-group">
                          <label class = "control-label col-md-3 col-sm-3 col- 
 xs-12">Nouveau Type<span class = "required">*</span></label>
                          <div class = "col-md-6 col-sm-6 col-xs-12">
                            <input [(ngModel)] = "typePrestataire" 
 name = "typePrestataire" class = "form-control col-md-7 col-xs-12" type = "text" 
 required>
                          </div>
                          <button type = "button" class = "btn btn-success" 
 (click) = "ajouterTypesPrestataires()">Ajouter</button>

                        </div>

                      </form>
                    </div>
                    <div class = "modal-footer">
                      <button type = "button" class = "btn btn-danger" data- 
 dismiss = "modal" id = "fermer">Fermer</button>
                    </div>
                  </div>
                </div>
              </div>
              <!--  /modal -->

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
  12">Photo/Logo<span class = "required">*</span></label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <input name = "multipartFile" class = "form-control col-md-7 
 col-xs-12"
                         type = "file" required = "required"
                         (change) = "handleFileInput($event)">
                </div>
              </div>

              <div class = "form-group">
                <label class = "control-label col-md-3 col-sm-3 col-xs- 
  12">Image Preview</label>
                <div class = "col-md-6 col-sm-6 col-xs-12">
                  <img class = "imagePrestataires" [src] = "imageURL">
                </div>
              </div>

              <div class = "form-group">
                <div class = "col-md-6 col-sm-6 col-xs-12 col-md-offset-3">
                  <button class = "btn btn-warning" 
 type = "reset">Vider</button>
                  <button type = "button" class = "btn btn-success" 
 (click) = "ajouterPrestataires()">Ajouter</button>
                </div>
              </div>
            </form>

          </div>
          </div>

        </div>
      </div>
    </div>
  </div>
 </div>

Вот Service.ts

import {Injectable} from "@angular/core";
import {HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpRequest} from 
"@angular/common/http";

 @Injectable()
 export class PrestatairesService
  {
   host:string = "http://localhost:8080/";
   constructor(private http:HttpClient)
  {

  }

getAllTypes()
{
  return this.http.get(this.host + "prestatairesTypes");
}

 ajouterType(model:any)
 {
   return this.http.post(this.host + "prestatairesTypes", model);
 }

 getOneType(id:any)
 {
   return this.http.get(this.host + "prestatairesTypes/" + id);
 }

 ajouterPrestataires(model:any)
 {
   return this.http.post(this.host + "prestataires", model);
 }

 uploadFile(model:any)
 {

 let formData = new FormData();
 formData.append('multipartFile', model.file);
 formData.append('nom', model.nom);
 formData.append('email', model.email);
 formData.append('rib', model.rib);
 formData.append('taches', model.taches);
 formData.append('fax', model.fax);
  formData.append('adresse', model.adresse);

 // This is the line that cause the Error of status code 400
 // What to do here to send the request correctly
 formData.append('prestatairesTypes', model.prestatairesTypes);
 formData.append('tele', model.tele);

 let params = new HttpParams();

 const options = {
  params: params,
  reportProgress: true,
 };

 const req = new HttpRequest('POST', this.host+"prestataires", formData, 
  options);
 return this.http.request(req);
  }
 }

Вы пытались отправить запрос от почтальона?

Pranjal Gore 17.10.2018 22:22

я не сделал. я отправляю запрос из формы. запрос работает нормально, когда я удаляю эту строку кода formData.append ('prestatairesTypes', model.prestatairesTypes); в служебном файле. но я получаю нулевые данные в базе данных внешнего ключа

beyyato abdellah 17.10.2018 22:39

Я просто тестирую api с почтальоном. это дает мне ту же ошибку 400 (неверный запрос)

beyyato abdellah 17.10.2018 23:48

Не могли бы вы обновить код запроса, который вам сгенерировал почтальон?

Pranjal Gore 18.10.2018 04:55

POST / prestataires HTTP / 1.1 Хост: localhost: 8080 Content-Type: multipart / form-data; border = ---- WebKitFormBoundary7MA4YWxkTrZu0gW Cache-Control: no-cache Postman-Token: 3dd2ce54-e4cf-daed-bbb7-a22f627ce9a7 ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-Disposition: form name = "nom" sdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "email" sdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "теле"

beyyato abdellah 18.10.2018 12:14

sdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "rib" sdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "fax" sdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "adresse" sdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "taches" dsdsd ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "файл"; filename = "Jordanie.jpg" Content-Type: image / jpeg

beyyato abdellah 18.10.2018 12:14

------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "photo" ------ WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name = "prestatairesTypes" {"id": 1, "обозначение": "ff", "coproprietes": null} ------ WebKitFormBoundary7MA4YWxkTrZu0gW--

beyyato abdellah 18.10.2018 12:14

Для этого вопроса не было необходимости добавлять код внешнего интерфейса. Бланка почтальона, который вы отправили, было достаточно. Вы забыли добавить исключение серверной части, это было бы гораздо полезнее.

Yoshua Nahar 18.10.2018 14:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
801
1

Ответы 1

If you set the file name to multipartFile, it should work.

Проблема в том, что @RequestParam("multipartFile") MultipartFile file не получает файл, потому что нет поля формы с именем multipartFile. Это то, что вы настроили с помощью @RequestParam.

Это фрагмент почтальона, который вы можете использовать. Проверить последний параметр.

POST /prestataires HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
Postman-Token: 809c9cd4-8b66-43e6-939c-1f2a554ca982
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "nom"

NOM
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "email"

EMAIL
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "tele"

TELE
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "fax"

FAX
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "rib"

RIB
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "adresse"

ADRESSE
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "taches"

TACHES
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "photo"

PHOTO
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name = "multipartFile"; filename = "demo.txt"
Content-Type: text/plain


------WebKitFormBoundary7MA4YWxkTrZu0gW--

при отправке этого запроса на бэкэнд у меня была следующая ошибка: {"timestamp": 1539867360299, "status": 500, "error": "Internal Server Error", "exception": "org.springframework.web.multipart.MultipartException" , "message": "Текущий запрос не является составным", "path": "/ prestataires"}

beyyato abdellah 18.10.2018 14:55

Вы предоставляете файл, который действительно существует? Покажите нам исключение серверной части.

Yoshua Nahar 18.10.2018 15:01

это бэкэнд-заголовок ошибки: org.springframework.web.multipart.MultipartException: текущий запрос не является составным запросом

beyyato abdellah 18.10.2018 15:04

Отметьте этот ответ stackoverflow.com/a/42016651/5473627. Он также получает MultipartException, потому что он включил заголовок Content-Type. Убери это.

Yoshua Nahar 18.10.2018 15:10

после этого ответа у меня возникла ошибка кода состояния 400: {"timestamp": 1539868805973, "status": 400, "error": "Bad Request", "exception": "org.springframework.validation.BindException", " ошибки »: [{« коды »: [« typeMismatch.prestataires.prestatairesTypes »,« typeMismatch.prestatairesTypes »,« typeMismatch.smart.syndic.entities.PrestatairesTypes »,« typeMismatch »],« arguments »: [

beyyato abdellah 18.10.2018 15:23

Удалите код @ManyToOne @JoinColumn(name = "ID_PRESTATAIRES_TYPES") private PrestatairesTypes prestatairesTypes; ... Это уже другая проблема для другого вопроса :)

Yoshua Nahar 18.10.2018 15:24

{"коды": ["prestataires.prestatairesTypes", "prestatairesTypes"], "arguments": null, "defaultMessage": "prestatairesTypes", "code": "prestatairesTypes"}], "defaultMessage": "Не удалось преобразовать свойство значение типа java.lang.String для требуемого типа smart.syndic.entities.PrestatairesTypes для

beyyato abdellah 18.10.2018 15:24

свойство prestatairesTypes; вложенное исключение - org.springframework.core.convert.ConversionFailedException: не удалось преобразовать тип [java.lang.String] в тип [java.lang.Long] для значения '{\ "id \": 1, \ "обозначение \ ": \" ff \ ", \" coproprietes \ ": null} '; вложенное исключение - java.lang.NumberFormatException: для входной строки: \ "{\" id \ ": 1, \" обозначение \ ": \" ff \ ", \" coproprietes \ ": null} \" "‌, "objectName": "prestataires", "field": "prestatairesTypes", "rejectedValue": "{\" id \ ": 1, \" обозначение \ ": \" ff \ ", \" coproprietes \ ": null} ",

beyyato abdellah 18.10.2018 15:24

эта ошибка находится в почтальоне: "bindingFailure": true, "code": "typeMismatch"}], "message": "Ошибка проверки объекта = 'prestataires'. Количество ошибок: 1", "path": "/ prestataires" }

beyyato abdellah 18.10.2018 15:31

Покажите исключение, которое вы получили в своей консоли ide, плз

Yoshua Nahar 18.10.2018 15:32

Невозможно отправить объект, содержащий внешний ключ, - это мой главный вопрос в этом посте

beyyato abdellah 18.10.2018 15:35

у меня нет ошибки в Backend. ошибка 400. Я думаю, что запрос не доходит до серверной части, потому что он неправильно сформирован

beyyato abdellah 18.10.2018 15:35

Кто-нибудь может ответить на этот вопрос? пожалуйста

beyyato abdellah 19.10.2018 22:22

Другие вопросы по теме