【问题标题】:i try to upload image on the Nodejs server我尝试在 Nodejs 服务器上上传图像
【发布时间】:2021-05-08 20:30:01
【问题描述】:

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();
        })
      );
  }
}

模型文件可用Course.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);

控制器文件可用CourseController.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!!!"});
            });
        }
}

出现错误:

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)

【问题讨论】:

  • 错误是:TypeError:无法读取未定义的属性“文件名”

标签: node.js angular mongoose upload multer


【解决方案1】:

看到你的错误堆栈跟踪,很明显你的请求正文中的文件对象是未定义的,因此,试图访问未定义的文件名抛出 Cannot read property 'filename' of undefined

问题在于您从 Angular 向服务器发送文件数据的方法。您的表单通常需要enctype="multipart/formdata" 才能克服此类问题。幸运的是,Angular 有 Formdata 来处理 Multipart/formdata

将表单提交后触发的saveAvailableCourse() 函数更改为:

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)
    );
}

【讨论】:

  • 非常感谢您的帮助。问题解决了。
  • addEditAvailableCourse(data, file: File, id) { const formData = new FormData(); formData.append('图片', 文件); formData.append('selectCourse', data.selectCourse); formData.append('courseCode', data.courseCode); formData.append('courseFees', data.courseFees); var URL = BASE_URL + ((!this.studentCourseService.isUndefinedOrNull(id)) ? (ENV.UPDATE_AVAILABLE_COURSE_BY_ID + id) : ENV.CREATE_AVAILABLE_COURSE);返回 this.http.post(URL, formData); }
  • 不客气。另外,如果答案有帮助,您可以接受它作为正确答案。只有当它有帮助..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-07
  • 2020-12-02
  • 1970-01-01
  • 2013-12-20
  • 2014-08-05
  • 2021-05-20
  • 2015-01-28
相关资源
最近更新 更多