Cannot send a POST request that contain an object

2019-08-28 02:09发布

问题:

I have a Status Code 400in the frontend when i try to send a POST request with Angular 5 to Spring Boot Rest Controller.

Here is the Entity :

@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-------------------------------

}

Here is the Second Entity:

@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; 

 }

Here is the 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);              
 }

 }

Here is The Model Prestataires in 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;

  }

Here is the model PrestatairesTypes in TypeScript:

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

Here is the Angular Controller in 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.log("Added");
    this.getAllTypes();
    this.modelType = data;

   }, err=>{
    console.log("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=>{

  }, ()=>{

  });

 }

 }

Here is the View :

<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>

Here is the 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);
  }
 }

回答1:

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

The problem is that the @RequestParam("multipartFile") MultipartFile file isn't receiving the file, because there is no form field with the name multipartFile. That is what you configured with @RequestParam.

This is a postman snippet that you can use. Check the last parameter.

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--