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。
我已经调试了一整天,终于没有谷歌搜索选项了。
我有一个 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。