Angular 8 + Laravel 6 FormData

Issue

I have a front end application using angular 8 and api laravel 6. This application requires authentication to have access to the dashboard. In one of the modules, I need to upload an image in addition to other fields. However, my api always returns empty, even if I use the Angular’s FormData. I only return the fields I sent if I send a normal JSON, but I need to send an image too

my html:

<div class="row">
<div class="col-md-12">
        <h4 class="remove-margin">Adicionar novo professor </h4>
        <div class="card">
          <div class="card-header">
            <!-- <h5 class="card-title">Edit Profile</h5> -->
          </div>
          <div class="card-body">
            <form [formGroup]="registerForm" (ngSubmit)="registerProfessores()">
            <div class="row">
                <div class="col-md-12">
                    <div class="form-group">
                        <label>Foto</label>
                        <input class="form-control" name="foto" type="file" (change)="uploadFile($event)" >
                        <div *ngIf="fileUploadProgress">
                            Upload progress: {{ fileUploadProgress }}
                        </div>
                        <div class="image-preview mb-3" *ngIf="preview && preview !== null">
                            <img [src]="preview" height="300" />                 
                        </div>

                        <label for="file-upload" id="file-drag">
                            <img id="file-image" src="#" alt="Preview" class="hidden">
                            <div id="start" >
                                <i class="fa fa-download" aria-hidden="true"></i>
                                <div>Select a file or drag here</div>
                                <div id="notimage" class="hidden">Please select an image</div>
                                <span id="file-upload-btn" class="btn btn-primary">Select a file</span>
                                <br>
                                <span class="text-danger"></span>
                            </div>

                        </label>
                    </div>
                </div>
            </div>
              <div class="row">
                  <div class="col-md-12">
                      <div class="form-group">
                      <label>Nome</label>
                      <input type="text" name="nome" formControlName="nome" class="form-control" placeholder="Nome">

                      <small id="emailHelp" class="form-text text-muted" *ngIf="serverErrors">{{ serverErrors.name }}</small>

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

              <div class="row">
                <div class="col-md-12">
                    <div class="form-group">
                        <label>Currículo resumido</label>
                        <textarea name="curriculo" formControlName="curriculo" name="curriculo" class="form-control" placeholder="Currículo"></textarea>
                    </div>
                </div>
              </div>

              <div class="row">
                <div class="col-md-12">
                    <div class="form-group">
                        <label>Currículo Lates</label>
                        <input type="text" name="link" formControlName="link" name="link" class="form-control" placeholder="Currículo Lates" >
                    </div>
                </div>
              </div>

                <div class="row">
                  <div class="update ml-auto mr-auto">
                    <button type="submit" class="btn btn-primary btn-round" [disabled]="!registerForm.valid">Salvar</button>
                  </div>
                </div>
              </form>
          </div>
        </div>
      </div>

my component.ts

    ngOnInit() {
    this.registerForm = this.fb.group({
      nome: [''],
      curriculo: [''],
      link: [''],
      foto: [null]
    })
  }

  uploadFile(event){
    const file = (event.target as HTMLInputElement).files[0];
    this.registerForm.patchValue({
      foto: file
    })
    this.registerForm.get('foto').updateValueAndValidity();

    const reader = new FileReader();
    reader.onload = () => {
      this.preview = reader.result as string
    }
    reader.readAsDataURL(file);
  }

  registerProfessores(){ 
    this.professorRest.storeProfessor(this.registerForm).subscribe(
      response => {
        console.log('RESPONSE-----------',response),
        this.router.navigate(['professores'])
      },
      error =>{
        this.serverErrors = error.error.errors
      } 
    );
  } 

my service.ts

import { Injectable, ɵConsole } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/internal/Observable';

const HttpUploadOptions = {
  headers: new HttpHeaders({ "Content-Type": "multipart/form-data" })
}

@Injectable({
  providedIn: 'root'
})
export class ProfessorRestService {
  professores: Array<{id: number, nome: string, foto: string, curriculo: string}> = [];
  constructor(private http: HttpClient) { }

  getProfessores(): Observable<any> {
    return this.http.get('http://localhost/server/public/api/professor-list');
  }

  editProfessor(id): Observable<any> {
    return this.http.get('http://localhost/server/public/api/professor-list/' + id);
  }

  updateProfessor(form,id): Observable<any> {
    return this.http.put('http://localhost/server/public/api/professor-list/' + id, form.value);
  }

  storeProfessor(form): Observable<any> {

/*     const input = {
      nome: form.get('nome').value,
      curriculo: form.get('curriculo').value,
      link: form.get('link').value,
      foto: form.get('foto').value
    } */


    const input = new FormData();
    input.append('nome', form.value.nome)
    input.append('curriculo', form.value.curriculo)
    input.append('link', form.value.link)
    input.append('foto', form.value.foto)

    return this.http.post('http://localhost/server/public/api/professor-list',input,HttpUploadOptions);
  }

  deleteProfessor(id): Observable<any> {
    return this.http.delete('http://localhost/server/public/api/professor-list/' + id);
  }
}

my interceptor

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {    
    // note add this header for CORS pass
    let token = localStorage.getItem('token');
    let headers = null;

    if(token){
      headers = new HttpHeaders({
        'Content-Type' : 'application/form-data; charset=UTF-8, application/json',
        'Authorization' : `Bearer ${token}`,
      });
    }else{
      headers = new HttpHeaders({
        'Content-Type' : 'application/form-data; charset=UTF-8, application/json'
    });
    }
    const requestChange = req.clone({headers});
    console.log(requestChange);
    return next.handle(requestChange);
  }
} 

Here is my Controller in laravel

    <?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Professor;

class ProfessorListController extends Controller
{
    public function __construct()
    {
        //$this->middleware('auth:api');
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
        $professor = Professor::get();
        return response()->json(['professor' => $professor], 200);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {

        return response()->json(['TODOS' => $request->all()]);


        if($files = $request->file('foto')){
            $destinationPath = 'public/image/';
            $profileImage = date('YmdHis') .  "." . $files->getClientOriginalExtension();
            $files->move($destinationPath, $profileImage);
        }

        $professor = Professor::create([
            'nome' => $request->nome,
            'foto' => $profileImage,
            'curriculo' => $request->curriculo,
            'link' => $request->link
        ]);

        return response()->json(['professor' => "Professor criado com sucesso"], 200);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
        $professor = Professor::find($id);
        return response()->json(['professor' => $professor], 200);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
        $professor = Professor::find($id);
        return response()->json(['professor' => $professor], 200);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $professor = Professor::find($id);

        $professor->update($request->all());
        return response()->json(['professor' => $professor,'message' => 'Professor Updated Successfully'], 200);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $professor = Professor::find($id);
        $professor->delete();
        return response()->json(['professor' => $professor,'message' => 'Professor Deleted Successfully'], 200);
    }
}

backend response

front end

Solution

Problem solved. Just remove the ‘Content-type’ from the interceptor

my interceptor

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {    
    // note add this header for CORS pass
    let token = localStorage.getItem('token');
    let headers = null;

    if(token){
      headers = new HttpHeaders({

        'Authorization' : `Bearer ${token}`,
      });
    }else{
      headers = new HttpHeaders({

    });
    }
    const requestChange = req.clone({headers});
    console.log(requestChange);
    return next.handle(requestChange);
  }
} 

Answered By – Daniel Swater

Answer Checked By – Jay B. (AngularFixing Admin)

Leave a Reply

Your email address will not be published.