Vue Frontend -Multer Express -Req.file不确定

发布于 2025-01-17 23:23:29 字数 3074 浏览 1 评论 0原文

我整天都在调试,终于没有谷歌搜索。

我有一个接收图像的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;
});

出于空间原因,我省略了一些代码,但是由于某种原因,它只是行不通的。记录文件返回文件,但后端拒绝看到它。

谢谢扎克

I have been debugging this all day and am finally out of googling options.

I have a Vue3 frontend that receives an image and is supposed to send said image to the backend. I have verified that the image is, in fact, being sent, but the file object in Multer is showing undefined every time regardless of what the front-end / network says is being sent.

Here's my code

Frontend

<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>

Backend

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;
});

I omitted some code for space reasons, but for some reason it just won't work. Logged file returns a file, but the backend refuses to see it.

Thanks

  • Zach

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

末が日狂欢 2025-01-24 23:23:29

看来您的 Multer DiskStorage 配置是问题的原因。

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

请注意,destination 的文档指出...

如果传递了一个字符串并且目录不存在,Multer 会尝试递归地创建它

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

您的 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 作为开发依赖项安装,以便在编辑器中获得有用的 linting。

It seems your Multer DiskStorage configuration is the cause of the problems.

My guess is you have the wrong file paths because ./ is not what you think. This is why it's always good to resolve paths from __dirname (the current script's parent directory).

Note that the documentation for destination states...

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

So you'll need to manually create the upload directories since you're using the function version.

You also have the wrong argument type in your filename hook. The file argument is of type Express.Multer.File, not File. You don't need to set this as it's already defined by the function signature.

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
  }
});

Make sure you install @types/multer as a dev-dependency to get useful linting in your editor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文