1

i am working in a project in school, backend is a REST based on Spring Boot,
Frontend is an Angular 5 application. i have red a lot of tutorials but i cannot
find the right answer for my question:
-How can i post a form that contain an input of type file and others input of type text
-i want to send a form that contain a picture to backend, after that i want to take the file, rename it with unique name and upload it to a folder and put the URL in the DataBase
-i Have this Error in Backend :
Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value

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;
  private File file;

//-------------------Constructors--------------------

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

}

Here is the RestController Class :

package smart.syndic.web;


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 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 addPrestataires(
            @RequestBody Prestataires v) {
    /*
    Here will be the code to process the file coming from front End and
    uploading it to folder then put the URL to DataBase
    */
    return repository.save(v);
  }
}

Here is the front end App:

<form class="form-horizontal form-label-left" #f1="ngForm">
            <div id="containerAjouterPrestataires">

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

            <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="photo" class="form-control col-md-7 col-xs-12"
                       type="file" required="required" accept="image/*"
                        (change)="handleFileInput($event)">
              </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>

Here is the TypeScript Controller:

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;
email:any;
tele:any;
fax:any;
rib:any;
adresse:any;
taches:any;
photo:any;

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

}

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.file = this.fileToUpload;
  this.modelPrestataires.photo = this.photo;

  this.getOneType(this.selectTypes);
  this.modelPrestataires.prestatairesTypes = this.modelType;

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


console.log("Success");

    }, err=>{


console.log("Error");

    }, ()=>{

    });

    }

Here is the service :

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

 }
 uploadFile(model:any){

 let formData = new FormData();

  formData.append('fichier', model.file);

  let headers = new HttpHeaders().set('Content-Type','application/json');


  let params = new HttpParams();
  const options = {
  params: params,
  reportProgress: true,
  headers: headers
 };

 const req = new HttpRequest('POST', this.host + "prestataires", formData, 
 options);
 return this.http.request(req);
 }
 }
Yoshua Nahar
  • 1,304
  • 11
  • 28
beyyato abdellah
  • 127
  • 1
  • 2
  • 15
  • Could you share the exact exception you got in your backend? You are asking multiple questions btw... The three main ones: how to post files to a backend, how to handle multipart files in Spring, and how to store the file with JPA in the db are all already answered here. – Yoshua Nahar Oct 15 '18 at 17:39

1 Answers1

0

When uploading the file to the backend you can use Multipart file. You could also Base64 encode the file in the frontend and send it as a JSON string, but that causes a lot more bytes being sent over the wire.

In the multipart solution your controller should expect a multipart file like so.

Controller

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

  @RequestMapping(value="/prestataires", method=RequestMethod.POST)
  // you don't have to add @RequestBody for the Prestataires
  public String postFileUpload(Prestataires prestataires, @RequestParam("multipartFile") MultipartFile file) {
    // Make sure that in the frontend the name of the form field for the file is also multipartFile
   // Also make sure that the mime type in the frontend is multipart/form-data

    byte[] rawFile;

    try {
      rawFile = file.getBytes();
    } catch (IOException e) {
      e.printStackTrace();
      return "error?";
    }

    prestataires.setFile(rawFile);

    prestatairesRepository.save(prestataires);

    return "redirect:/ or send response";
  }

}

Your entity can't just have a File class as field. You need to have a byte[]; you will ultimately be storing raw bytes in your database - I think other datatypes are also allowed.

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
  @Column(name = "file", columnDefinition="BLOB")
  private byte[] file;

  //-------------------Constructors--------------------

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

}

For the Angular part I suppose this is a perfect example of what you need to upload files: https://stackoverflow.com/a/40216616/5473627

Yoshua Nahar
  • 1,304
  • 11
  • 28
  • Thanks a lot for your answers. but i have to send a form that contain 7 input of type text and an input of type file in the same object . and end it to backend. i don't know what to do in the backend to recieve the object sent. i am using @RequestBody but that seems not working – beyyato abdellah Oct 16 '18 at 10:40
  • You can send all the form fields from the frontend at once. Set the form name of the file to multipartFile. If you update your controller to what I have, it should work. – Yoshua Nahar Oct 16 '18 at 11:25
  • Thanks a lot @Yoshua Nahar for your reply. i did the same code that you supllied but i have this Error : C:\Users\Abdellah\AppData\Local\Temp\tomcat.8010839068277012209.8080\work\Tomcat\localhost\ROOT\upload_d5199625_6ed1_4e86_b536_6a1ae09835b3_00000000.tmp (The system cannot find the file specified) . Could you please continue helping me, because i am blocked for 3 days. if you have time you can teamviewer me please – beyyato abdellah Oct 16 '18 at 11:48
  • Forget about saving the a text file in a folder for a second. Focus on saving a picture in your database. Did you have any luck with that? What was your exception? – Yoshua Nahar Oct 16 '18 at 12:11
  • i have this error in the backend : java.io.FileNotFoundException:C:\Users\Abdellah\AppData\Local\Temp\tomcat.770516852089309773.8080\work\Tomcat\localhost\ROOT\upload_0623b463_e628_4dc2_adfc_11ebf60bf5ee_00000001.tmp (The system cannot find the file specified)
    in frontend i have a 400 status code
    – beyyato abdellah Oct 16 '18 at 12:21
  • I am not familiar with that exception message. You are getting that on startup right? Are you using Spring Boot? Try out this guide for kicks https://spring.io/guides/gs/uploading-files/ – Yoshua Nahar Oct 16 '18 at 12:57
  • i am getting this Error after sending request from browser to backend. yes i am using Spring Boot btw thanks a lot. – beyyato abdellah Oct 16 '18 at 13:48
  • Hi. i have resolved the problem of uploading file and storing it to DataBase.also uploading the entire form. but i have an other Error in the frontend side of type 400 .i have a foreign key that fire this error. could you please help Me.?please add me in hangout to tell you the entire probleme. beyyatoabdellah@gmail.com – beyyato abdellah Oct 17 '18 at 14:04
  • Sorry, Im usually at work when I check stackoverflow and can't call or whatever. If your initial question has been resolved, avoid asking questions to other issues in the comments. Ask another question or check if a similar question have already been answered. – Yoshua Nahar Oct 17 '18 at 14:38
  • this is updated question for my new Error https://stackoverflow.com/questions/52861956/cannot-send-a-post-request-that-contain-an-object-foreign-key-with-angular-5-t – beyyato abdellah Oct 18 '18 at 11:43