Vue 前端 - Multer Express - Req.File 未定义

Vue Frontend - Multer Express - Req.File is undefined

我已经调试了一整天,终于没有谷歌搜索选项了。

我有一个 Vue3 前端,它接收图像并应该将所述图像发送到后端。我已经验证图像实际上正在发送,但是 Multer 中的文件对象每次都显示未定义,无论前端/网络说正在发送什么。

这是我的代码

前端

<template>
  <div class="flex justify-center">
    <div class="mb-3 w-96">
      <label for="formFile" class="form-label inline-block mb-2 text-gray-700"
        >Upload a new profile picture</label
      >
      <input
        class="form-control block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
        type="file"
        @change="onSelect"
        id="formFile"
      />
      <span class="message"> {{ message }} </span>
    </div>
  </div>
</template>
<script>
import axios from "redaxios";
export default {
  name: "FileUpload",
  props: {
    user: Array | Object,
  },
  created() {},
  data() {
    return {
      file: "",
      message: "",
    };
  },
  methods: {
    onSelect(e) {
      this.file = e.target.files[0] || e.dataTransfer.files;
      if (this.file.length) return;
      const formData = new FormData();
      console.log(this.file);
      formData.append("id", this.user.id);
      formData.append("file", this.file);
      //formData.set("enctype", "multipart/form-data");
      console.log(formData);
      try {
        axios
          .post("http://localhost:3669/uploadPhoto", formData)
          .then((res) => {
            this.message = "Uploaded successfully!";
          });
      } catch (err) {
        console.log(err);
        this.message = "Something went wrong uploading your photo!";
      }
    },
  },
};
</script>

后端

const fileFilter = (req: express.Request, file: File, cb) => {
    const allowedTypes = /jpeg|jpg|png|gif/;
    const extname = allowedTypes.test(path.extname(file.name).toLowerCase());
    const mimetype = allowedTypes.test(file.type);
    if (!mimetype && extname) {
        const error = new Error("Incorrect Filetype");
        error.name = "INCORRECT_FILETYPE";
        return cb(error, false);
    }
    cb(null, true);
}

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        if (req.body.id) {
            cb(null, `./public/photos/${req.body.id}`)
        } else {
            cb(null, "./public/photos");
        }
    },
    filename: function (req, file: File, cb) {
      console.log(req.file);
  
      cb(null, file.name + ".png");
    },
  });

const imageUpload : Multer = multer({
    storage,
    limits: {
        fileSize: 5000000
    }
});

app.post('/uploadPhoto', imageUpload.single('file'), async (req: express.Request, res:express.Response) => {
    console.log(req.body);
    console.log(req.file);
    res.json({ message: 'Successfully uploaded file' });
    return;
});

出于 space 的原因,我省略了一些代码,但由于某些原因它无法正常工作。记录文件 returns 一个文件,但后端拒绝查看它。

谢谢

您的 Multer DiskStorage 配置似乎是问题的原因。

我猜你的文件路径有误,因为 ./ 不是你想的那样。这就是为什么从 __dirname(当前脚本的父目录)解析路径总是好的原因。

请注意 destination 的文档说明...

If a string is passed and the directory does not exist, Multer attempts to create it recursively

因此您需要手动创建上传目录,因为您使用的是功能版本。

您的 filename 挂钩中的参数类型也有误。 file 参数的类型是 Express.Multer.File,而不是 File。您不需要设置它,因为它已经由函数签名定义。

import { resolve } from "path";
import { mkdir } from "fs/promises";
import multer from "multer";

const uploadBase = resolve(__dirname, "./public/photos");

const storage = multer.diskStorage({
  destination: async (req, _file, cb) => {
    const path = req.body.id ? resolve(uploadBase, req.body.id) : uploadBase;
    try {
      // create the directory
      await mkdir(path, { recursive: true });
      cb(null, path);
    } catch (err) {
      cb(err);
    }
  },
  filename: (_req, file, cb) => {
    cb(null, file.originalname); // note the property used
  }
});

确保将 @types/multer 安装为 dev-dependency 以便在编辑器中获得有用的 linting。