i try to upload image on the Nodejs server

Viewed 65

AvailableCourseAddEditComponent.html

<div class="main-content">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">
                <div class="col-md-12 grid-margin stretch-card">
                    <div class="card">
                        <div class="header">
                            <h4 class="title">{{(availableCourseId)? 'Edit Course' : 'Add Course'}}</h4>
                        </div>
                        <div class="card-body">

                            <form [formGroup]="availableCourseForm" novalidate (ngSubmit)="saveAvailableCourse()">

                                <div class="row">
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label>Select Course<span class="text-danger">&nbsp;*</span></label>
                                            <select formControlName="selectCourse" class="form-control"
                                                [ngClass]="{ 'is-invalid': submitted && frm.selectCourse.errors }">
                                                <option value="" disabled selected hidden>Select Course</option>
                                                <option *ngFor="let allcourse of studentCourse;">{{allcourse.course}}
                                                </option>
                                            </select>
                                            <div *ngIf="submitted && frm.selectCourse.errors"
                                                class="text-danger invalid-feedback">
                                                <div *ngIf="frm.selectCourse.errors.required">Select atleast one course
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label>Course Code<span class="text-danger">&nbsp;*</span></label>
                                            <input type="text" placeholder="Enter Course Code"
                                                formControlName="courseCode" class="form-control"
                                                [ngClass]="{'is-invalid': submitted && frm.courseCode.errors}">
                                            <div *ngIf="submitted && frm.courseCode.errors"
                                                class="text-danger invalid-feedback">
                                                <div *ngIf="frm.courseCode.errors.required">Course code is required
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <div class="row">
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <label>Course Fees<span class="text-danger">&nbsp;*</span></label>
                                            <input type="number" placeholder="e.g 2000" formControlName="courseFees"
                                                class="form-control"
                                                [ngClass]="{'is-invalid': submitted && frm.courseFees.errors}">
                                            <div *ngIf="submitted && frm.courseFees.errors"
                                                class="text-danger invalid-feedback">
                                                <div *ngIf="frm.courseFees.errors.required">Course Fees is required
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <div class="form-group">
                                            <input type="file" formControlName="image" (change)="selectImage($event)" />
                                        </div>
                                    </div>
                                </div>


                                <button type="submit" class="btn btn-gradient-primary mr-2">
                                    {{(availableCourseId)? 'Edit' : 'Add '}}Course
                                </button>
                                <button class="btn btn-light" routerLink="/available-course">Cancel</button>

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

AvailableCourseAddEditComponent.ts

    import { Component, OnInit } from '@angular/core';
    import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
    import { Router, ActivatedRoute } from '@angular/router';
    import { StudentCourseService } from '../../../services/student-course.service';
    import { AvailableCourseService } from '../../../services/available-course.service';
    
    @Component({
      selector: 'app-available-course-add-edit',
      templateUrl: './available-course-add-edit.component.html',
      styleUrls: ['./available-course-add-edit.component.scss']
    })
    export class AvailableCourseAddEditComponent implements OnInit {
    
      availableCourseForm: FormGroup;
      submitted = false;
      availableCourseId: number;
      studentCourse: any = [];
      images: any;
    
      constructor(private fb: FormBuilder,
                  private router: Router,
                  private route: ActivatedRoute,
                  private studentCourseService: StudentCourseService,
                  private availableCourseService: AvailableCourseService) { 
                    this.createForm();
                    this.getAllCourse();
                  }
    
      ngOnInit(): void {
        // this.getStudentCourse();
        this.route.params.subscribe(params => {
          this.availableCourseId = params['availableCourseId'];
          console.log(this.availableCourseId);
          if(!this.studentCourseService.isUndefinedOrNull(this.availableCourseId)){
      }
    })
  }

  selectImage(event) {
    if (event.target.files.length > 0) {
      const file = event.target.files[0];
      this.images = file;
    }
  }

  createForm() {
    this.availableCourseForm = this.fb.group({
      selectCourse : ['', Validators.required],
      courseCode: ['', Validators.required],
      courseFees: ['', Validators.required],
      image: ['']
    });
  }

  get frm() {
    return this.availableCourseForm.controls;
  }

  getAllCourse() {
    this.studentCourseService.getAllStudentCourse()
      .subscribe (
        (async (data: any) => {
          console.log("All Course List: ", data);
          this.studentCourse = (data && data.data)? data.data : [];
        })
      )
  }

  saveAvailableCourse() {
    this.submitted = true;
    console.log("Form value: ",this.availableCourseForm.value);

    if (this.availableCourseForm.invalid) {
      this.availableCourseForm.get('selectCourse').markAsTouched();
      this.availableCourseForm.get('courseCode').markAsTouched();
      this.availableCourseForm.get('courseFees').markAsTouched();
      this.availableCourseForm.get('image').markAsTouched();
      return;
    }

    this.availableCourseService.addAvailableCourse(this.availableCourseForm.value)
      .subscribe(
        (async(data: any) => {
          console.log("availableCourse added: ", data);
          this.availableCourseForm.reset();
        })
      );
  }
}

Model file availableCourse.js

const mongoose = require('mongoose');
const availableCourseSchema = mongoose.Schema({
    selectCourse: String,
    courseCode: String,
    courseFees: Number,
    file: String,
    isDeleted: false
}, 
{timestamps: true});

module.exports = mongoose.model('availableCourse', availableCourseSchema);

Controller file availableCourseController.js

const AvailableCourse = require('../Models/availableCourse');
const multer = require('multer');
const express = require('express');
const router = express.Router();

router.use(express.static(__dirname+"./public/"));

const Storage = multer.diskStorage({
    destination: function (Req, file, cb) {
        cb(null, "./public/uploads");
    },
    filename: function(req, file, cb) {
        cb(null, `${Date.now()}_${file.originalname}`);
    },
});

const upload = multer({ Storage }).single('image');

// Insert Course By Id:
exports.create = (req, res) => {

    availableCourse = {
        selectCourse: req.body.selectCourse,
        courseCode: req.body.courseCode,
        courseFees: req.body.courseFees,
        file: req.file.filename,
        isDeleted: false
    };
    console.log("AvailableCourse: ", availableCourse);
    AvailableCourse.create(availableCourse,upload, function(err, result) {
        if(err) {
            res.send({ status: "fail", message: "Fail too add availableCourse!", err: err});
        }
            res.send({ status: "success", message: "Course added Successfully!!!", data: result});
    });
}

// Update Course By Id: 
exports.update = (req, res) => {

    if(!req.params.Id) {
        res.send({
            status:"fail",
            message: "course not found with Id!" + req.params.Id
        });
    }
        AvailableCourse.findByIdAndUpdate(req.params.Id, { $set: req.body}, {new: false}, function(err, result) {
            if(err) {
                res.send({ status: "fail", message: "course not updated with Id!", err:err});
            }
                res.send({ status: "success", message: "course updated with successfully!!!", data: result});
        });
}

// Get All available Course:
exports.findAll = (req, res) => {

    AvailableCourse.find( {isDeleted: false})
        .then(availableCourse => {
            if(!availableCourse)
                res.json({ status: "fail", message: "fail too get all availableCourse!"});
            else
                res.json({ status: "success", message: "availableCourse find succesfully!!!", data: availableCourse});                
        })
        .catch(err => {
            res.json({
                status: "fail",
                message: err.message || "some error occurred"
            });
        });
}

// Get available Course By Id:
exports.getavailableCourseById = (req, res) => {
    if (!req.params.Id) {
        res.send({
            status: "fail",
            message: "course not found with Id!" + req.params.Id
        });
    }
    AvailableCourse.findById(req.params.Id)
        .then(availableCourse => {
            if(!availableCourse)
                res.json({ status: "fail", message: "fail to get customer!"});
            else
                res.json({ status: "success", message: "availableCourse found successfully!!!", data: availableCourse});             
        }).catch(err => {
            res.send({
                message: err.message || "some error occurred while retriving course"
            });
        });
}

// Delete Course By Id:
exports.delete = (req, res) => {
    if(!req.params.Id) {
        res.send({
            status: "fail",
            message: "available course not found with Id " + req.params.Id
        });
    }
        else{
            AvailableCourse.findByIdAndUpdate(req.params.Id, { $set: {isDeleted: true}}, {new: false}, function(err, result) {
                if (err) {
                    res.send({ status: "error", message: err});
                }
                    res.send({ status: "success", message: "availableCourse deleted successfully!!!"});
            });
        }
}

getting error:

E:\ANGULAR-PROJECTS\Company\projectTwo\Backend>nodemon server.js
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
(node:16860) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
(Use `node --trace-deprecation ...` to show where the warning was created)
listening on port: 5000
Connected to the Database.
TypeError: Cannot read property 'filename' of undefined
    at exports.create (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\Controllers\availableCourse-controller.js:26:24)
    at Layer.handle [as handle_request] (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\layer.js:95:5)
    at next (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\layer.js:95:5)
    at E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:335:12)
    at next (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:275:10)
    at Function.handle (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:174:3)
    at router (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:47:12)
    at Layer.handle [as handle_request] (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:317:13)
    at E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:335:12)
    at next (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\express\lib\router\index.js:275:10)
    at cors (E:\ANGULAR-PROJECTS\Company\projectTwo\Backend\node_modules\cors\lib\index.js:188:7)
1 Answers

Seeing your error stacktrace, it is clear that the file object in your request body is undefined, hence, trying to access filename of undefined throws Cannot read property 'filename' of undefined

The issue is with your method of sending file data to server from Angular. Your form need to have enctype="multipart/formdata" normally to overcome such issues. Luckily, angular has Formdata to deal with Multipart/formdata.

Change your saveAvailableCourse() function that is triggered after form submission to this:

saveAvailableCourse() {
    const formData = new FormData();
    formData.append('image', this.availableCourseForm.get('image').value);
    // ---- add other data as key value pair on form data here ----

    // sending request to server with formdata as payload
    this.httpClient.post<any>(SERVER_URL, formData).subscribe(
      (res) => console.log(res),
      (err) => console.log(err)
    );
}
Related