'Error when saving image data and form data in angular

I am implement an image upload feature to a form using multer and MEAN stack. the problem is i believe im passing the wrong set of data into the function which post the data to the server. I am unsure as to what is the correct format for the variable such that it is sent to the api server.

It returns the error:

message: 'Please upload an image' the component.html:

<div class="container">
  <!--Navbar-->
  <mat-toolbar color="primary">
    <div class="centerNavBar">
      <a mat-button href="fa-dashboard">Back</a>
      &nbsp;
      <span class="headSpacer">Damage Assessment Tool</span>
      &nbsp;
      <a mat-button href="">Logout</a>
    </div>
  </mat-toolbar>
</div>

<div>
  <mat-sidenav-container class="MainContainter">
    <!--SideNav-->
    <mat-sidenav mode="side" opened>
      <div>
        <a mat-button href="">Message Board</a>
      </div>
    </mat-sidenav>
    <mat-sidenav-content class="MainContent">
      <mat-card>
        <mat-card-header class="sect">Create report:</mat-card-header>
        <br /><br />
        <mat-card-content>
          <!--Div for form-->
          <div>
            <form>
              <mat-form-field>
                <input 
                #MOCDateInput
                matInput 
                type="Date" 
                required />
              </mat-form-field>
              <br />
              <mat-form-field>
                <mat-label>Comment</mat-label>
                <input
                  #DescriptionInput
                  placeholder="--"
                  matInput
                  type="string"
                  required
                />
              </mat-form-field>
              <br />
              <mat-form-field>
                <mat-label>Facility In Question</mat-label>
                <input
                  #MOCFacilityInput
                  placeholder="--"
                  matInput
                  type="string"
                  required
                />
              </mat-form-field>
            </form>
          </div>
        </mat-card-content>
      </mat-card>
      <mat-card>
        <h3>Select Location</h3>
        <mat-card-content>
          <!--Div for Map-->
          <div class="MOCMap">
            <div class="map-container">
              <div class="map-frame">
                <div id="map"></div>
              </div>
            </div>
          </div>
        </mat-card-content>
      </mat-card>
      <mat-card>
        <mat-card-actions>
          <!--Div for buttons-->
          <div>
            <input
              style="display: none"
              #ImageInput
              type="file"
              (change)="onFileSelected($event)"
            />
            <button
              mat-raised-button
              type="button"
              (click)="ImageInput.click()"
            >
              Upload Images
            </button>
            &nbsp;
            <button
              mat-raised-button
              type="submit"
              (click)="
                createMOCForm(
                  MOCFacilityInput.value,
                  DescriptionInput.value,
                  MOCDateInput.value
                )
              "
              color="primary"
            >
              Submit Report
            </button>
          </div>
        </mat-card-actions>
      </mat-card>
    </mat-sidenav-content>
  </mat-sidenav-container>
</div>

I believe however the problem lies in the typescript file on how i save both components, as i am using formData.append in the create function component.ts:

import { AfterViewInit, Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormGroup, FormControl } from '@angular/forms';

import { MOCReport } from 'src/app/models/mocreport.interface';

import { MOCReportService } from 'src/app/service/mocreport.service';


@Component({
  selector: 'app-moc-report',
  templateUrl: './moc-report.component.html',
  styleUrls: ['./moc-report.component.css'],
})
export class MocReportComponent implements OnInit
{
  form: FormGroup;
  mocReport: MOCReport;
  imageData;

  constructor(
    private mocreportservice: MOCReportService,
    private router: Router
  ) {}


  onFileSelected(event) {
    console.log("Select Image")
    if (event.target.files.length > 0) {
      const file = event.target.files[0];
      this.imageData = file;
    }
  }


  createMOCForm(
    facilityName: string,
    MoCDescription: string,
    MoCReportDateTimeString: string
  ) {
    //IMAGE POST
    const formData = new FormData();

    formData.append('mocImage', this.imageData);

    const MoCReportDateTime = new Date(MoCReportDateTimeString);
    this.mocreportservice
      .createMOCReport(
        facilityName,
        MoCDescription,
        MoCReportDateTime,
        formData
      )
      .subscribe((report: MOCReport) => {
        console.log(report);
        this.router.navigate(['/message-board']);
      });
  }

  ngOnInit(): void {
    
  }}

Service Associated, service.ts:

createMOCReport(facilityName: string, MoCDescription: string, MoCReportDateTime: Date, mocImage: any){
    return this.webReqService.post('MOCReport', {facilityName, MoCDescription, MoCReportDateTime, mocImage})
  }

  getMOCReport(){
    return this.webReqService.get('MOCReport');
  }

interface:

export interface MOCReport{
    _id: string;
    facilityName: string;
    MoCDescription: string;
    MoCReportDateTime: Date;
    MoCDisasterLocation: Array<number>;
    mocImage: File;
}

//////////////////////////////////////////////

Backend code for context:

controller (post function):

exports.MOCReport_post = (req, res, next) => {
  const mocImage = req.file;
  //console.log(mocImage.filename);
  if(!mocImage){
      const error = new Error('Please upload an image')
      error.httpStatusCode = 400
      return next (error)
  }
  let newMOCReport = new MOCReport({
    facilityName: req.body.facilityName,
    MoCDescription: req.body.MoCDescription,
    MoCReportDateTime: req.body.MoCReportDateTime,
    MoCDisasterLocation: req.body.MoCDisasterLocation,
    mocImage: req.file.path
  });
  newMOCReport.save().then((MOCReportDoc) => {(including id)
    res.send(MOCReportDoc);
  });
};

Router:

const storage = multer.diskStorage({
    destination: function(req, file, cb) {
         cb(null, './uploads/');
    },
    filename: function(req, file, cb) {
         cb(null, new Date().toISOString().replace(/:/g, '-') + file.originalname);
    }
 });
 const fileFilter = (req, file, cb) => {
    // reject a file
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png' || file.mimetype === 'image/jpg') {
      cb(null, true);
    } else {
      cb(null, false);
    }
  };
 
 const upload = multer({storage: storage, 
    limits: {
    fileSize: 1024 * 1024 * 5
  },
  fileFilter: fileFilter});


router.get('/MOCReport', MOCReportController.MOCReport_get_all)
router.get('/MOCReport/:mocreportID', MOCReportController.MOCReport_get_one)
router.post('/MOCReport', upload.single('mocImage'), MOCReportController.MOCReport_post);

How can i save both the image and the form data within the same function. Any help would be appreciated. thank you in advance.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source