我尝试在 Nodejs 服务器上上传图像

Posted

技术标签:

【中文标题】我尝试在 Nodejs 服务器上上传图像【英文标题】:i try to upload image on the Nodejs server 【发布时间】: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:无法读取未定义的属性“文件名” 【参考方案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); 不客气。另外,如果答案有帮助,您可以接受它作为正确答案。只有当它有帮助..

以上是关于我尝试在 Nodejs 服务器上上传图像的主要内容,如果未能解决你的问题,请参考以下文章

使用 multer-s3 nodejs 将图像上传到亚马逊 s3

使用改造 2 将图像从画廊/相机上传到服务器(okhttp 问题)

如何使用 NodeJS 将文件或图像上传到服务器

图像上传失败 w/nodejs express

Objective C - NodeJS - 如何将特定文件(不是图像)从 iOS 应用程序上传到服务器?

使用 NodeJS 的 Slack API (files.upload)