使用 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收到请求,文件上传成功