我尝试在 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"> *</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"> *</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"> *</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 问题)