使用 Angular、Node、Express、Multer 的图片上传问题
Image Upload Issue using Angular, Node, Express, Multer
我一直在遵循一些关于如何上传图片的指南(例如 , ),但我在将图片上传到后端目录时遇到了问题。这是我的代码:
Angular 前端
//html
<input type="file" name="image" (change)="onFileSelected($event)">
<button (click)="uploadImage()">Save Image</button>
//ts
formData = new FormData();
onFileSelected(event) {
this.uploadedImage = event.target.files[0]
}
uploadImage() {
if (this.uploadedImage) {
this.formData.append('image', this.uploadedImage, this.uploadedImage.name)
console.log(this.formData.getAll('image')) //confirms file is being uploaded properly
this.httpService.upload('uploadImage/', this.formData).subscribe((message: any) => {
console.log(message)
});
}
//httpService
upload(url, file) {
console.log("uploading file")
return this.http.post(this.baseUrl + url, file);
}
节点后端
//index.js
var http = require('http');
var express = require('express');
var cors = require('cors');
var app = express();
var multer = require('multer')
var path = require('path')
var bodyParser = require('body-parser');
app.use(cors());
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.resolve(__dirname, '../documents/'));
},
filename: (req, file, cb) => {
console.log(file);
cb(null, Date.now() + path.extname(file.originalname));
}
});
const fileFilter = (req, file, cb) => {
if (file.mimetype == 'image/jpeg' || file.mimetype == 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
}
const upload = multer({ storage: storage, fileFilter: fileFilter });
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:4200");
res.header('Access-Control-Allow-Methods', 'GET,POST,PATCH,PUT,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
next();
})
// other API requests...
app.post('/api/uploadImage/', upload.single('image'), (req, res, next) => {
console.log(req.file) //returns undefined
try {
return res.status(201).json({
message: 'File uploaded successfully'
});
} catch(error) {
console.error(error);
}
});
var server = http.createServer(app)
server.listen(5000, function() {
console.log('Http Server is up and running.');
}
我在 HttpService 完成后从后端收到消息 'File uploaded successfully',但我的 /documents/ 目录中没有图像。据我所知,图像应该通过 req.file 或 req.files 变量传过来,但 returns 未定义。我在这里做错了什么?
问题出在您的 Angular 应用程序的输入字段中。您的 ngModel
没有做任何事情,因为没有正确的语法,即使如此,它也只会保存图像的假路径。
有几种方法可以从输入字段中获取实际的文件对象。最简单的一种是使用 onChange
事件。它会是这样的:
<input type="file" name="image" (change)="onChange($event)">
在你的 TS 文件中:
onChange(event: any) {
this.uploadedImage = event.target.files[0];
}
您还需要更新服务中的上传方法,因为 multer
解析 FormData,因此您必须将数据作为 FormData 发送。
const data = new FormData();
data.append('image', this.file, this.file.name);
return this.http.post(this.baseUrl + url, data);
注意:您正在从后端获得“文件上传成功”,因为即使没有数据要处理,multer 也不会抛出错误,因此您的上传端点将始终 return 成功代码 201,甚至如果实际上没有上传文件。
我发现这个问题与FormData无法传输到后端有关,需要正确编码。根据解释 here,我将 HTML 更改为如下所示:
<form enctype="multipart/form-data" (ngSubmit)="uploadImage()">
<input type="file" name="image" (change)="onFileSelected($event)">
<button>Save Image</button>
</form>
后台通过req.body收到请求,文件上传成功
我一直在遵循一些关于如何上传图片的指南(例如
Angular 前端
//html
<input type="file" name="image" (change)="onFileSelected($event)">
<button (click)="uploadImage()">Save Image</button>
//ts
formData = new FormData();
onFileSelected(event) {
this.uploadedImage = event.target.files[0]
}
uploadImage() {
if (this.uploadedImage) {
this.formData.append('image', this.uploadedImage, this.uploadedImage.name)
console.log(this.formData.getAll('image')) //confirms file is being uploaded properly
this.httpService.upload('uploadImage/', this.formData).subscribe((message: any) => {
console.log(message)
});
}
//httpService
upload(url, file) {
console.log("uploading file")
return this.http.post(this.baseUrl + url, file);
}
节点后端
//index.js
var http = require('http');
var express = require('express');
var cors = require('cors');
var app = express();
var multer = require('multer')
var path = require('path')
var bodyParser = require('body-parser');
app.use(cors());
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.resolve(__dirname, '../documents/'));
},
filename: (req, file, cb) => {
console.log(file);
cb(null, Date.now() + path.extname(file.originalname));
}
});
const fileFilter = (req, file, cb) => {
if (file.mimetype == 'image/jpeg' || file.mimetype == 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
}
const upload = multer({ storage: storage, fileFilter: fileFilter });
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:4200");
res.header('Access-Control-Allow-Methods', 'GET,POST,PATCH,PUT,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
next();
})
// other API requests...
app.post('/api/uploadImage/', upload.single('image'), (req, res, next) => {
console.log(req.file) //returns undefined
try {
return res.status(201).json({
message: 'File uploaded successfully'
});
} catch(error) {
console.error(error);
}
});
var server = http.createServer(app)
server.listen(5000, function() {
console.log('Http Server is up and running.');
}
我在 HttpService 完成后从后端收到消息 'File uploaded successfully',但我的 /documents/ 目录中没有图像。据我所知,图像应该通过 req.file 或 req.files 变量传过来,但 returns 未定义。我在这里做错了什么?
问题出在您的 Angular 应用程序的输入字段中。您的 ngModel
没有做任何事情,因为没有正确的语法,即使如此,它也只会保存图像的假路径。
有几种方法可以从输入字段中获取实际的文件对象。最简单的一种是使用 onChange
事件。它会是这样的:
<input type="file" name="image" (change)="onChange($event)">
在你的 TS 文件中:
onChange(event: any) {
this.uploadedImage = event.target.files[0];
}
您还需要更新服务中的上传方法,因为 multer
解析 FormData,因此您必须将数据作为 FormData 发送。
const data = new FormData();
data.append('image', this.file, this.file.name);
return this.http.post(this.baseUrl + url, data);
注意:您正在从后端获得“文件上传成功”,因为即使没有数据要处理,multer 也不会抛出错误,因此您的上传端点将始终 return 成功代码 201,甚至如果实际上没有上传文件。
我发现这个问题与FormData无法传输到后端有关,需要正确编码。根据解释 here,我将 HTML 更改为如下所示:
<form enctype="multipart/form-data" (ngSubmit)="uploadImage()">
<input type="file" name="image" (change)="onFileSelected($event)">
<button>Save Image</button>
</form>
后台通过req.body收到请求,文件上传成功