我有一个表格,要在数据库中添加wine 店.我使用的是react 挂钩形式.在表单中,我还要求将图像作为输入.在提交表单时,表单中的数据被转换为表单数据,然后发送到API.
这就是正在进行转换和提交表格的地方.
以下是我的API调用:
const formMethods = useForm<HotelFormData>();
//we are not gonna destruct the formMethods object here
const { handleSubmit } = formMethods;
const onSubmit = handleSubmit((data: HotelFormData) => {
console.log(data);
//We are going to send the data to the server, but first we need to convert the data to FormData because we have imageFiles in the data and we can not send it as a JSON object
const formData = new FormData();
formData.append("name", data.name);
formData.append("city", data.city);
formData.append("country", data.country);
formData.append("description", data.description);
formData.append("type", data.type);
formData.append("pricePerNight", data.pricePerNight.toString());
formData.append("starRating", data.starRating.toString());
formData.append("adultCapacity", data.adultCapacity.toString());
formData.append("childCapacity", data.childCapacity.toString());
data.facilities.forEach((facility, index) => {
formData.append(`facilities[${index}]`, facility);
});
// for (let i = 0; i < data.imageFiles.length; i++) {
// formData.append("imageFiles", data.imageFiles[i]);
// }
Array.from(data.imageFiles).forEach((imageFile) => {
formData.append("imageFiles", imageFile);
});
onSave(formData);
console.log(formData);
});
export const addMyHotel = async (formData: FormData) => {
console.log("formData",formData)
const response = await fetch(`${BASE_URL}/api/my-hotels`, {
method: "POST",
credentials: "include", //to send the cookie
body: formData,
});
const resBody = await response.json();
if (!response.ok) {
throw new Error(resBody.message);
}
return resBody;
};
这是我的api/my-hotels
分:
import express from "express";
import { Request, Response } from "express";
import { PutObjectCommand } from "@aws-sdk/client-s3";
import mime from "mime-types";
import { client } from "../index";
import multer from "multer";
import Hotel, { HotelType } from "../models/hotel";
import verifyToken from "../middleware/auth";
import { body, validationResult } from "express-validator";
const router = express.Router();
const storage = multer.memoryStorage();
const upload = multer({
storage: storage,
limits: {
fileSize: 5 * 1024 * 1024, // 5MB
},
});
//this will be the root
router.post(
"/",
verifyToken, //only logged in users can create hotels
[
body("name").notEmpty().withMessage("Name is required"),
body("city").notEmpty().withMessage("City is required"),
body("country").notEmpty().withMessage("Country is required"),
body("description").notEmpty().withMessage("Description is required"),
body("type").notEmpty().withMessage("Type is required"),
body("pricePerNight")
.notEmpty()
.isNumeric()
.withMessage("Price per night must be a number"),
body("adultCapacity")
.notEmpty()
.isNumeric()
.withMessage("Adult capacity must be a number"),
body("childCapacity")
.notEmpty()
.isNumeric()
.withMessage("Child capacity must be a number"),
body("starRating")
.notEmpty()
.isNumeric()
.withMessage("Star rating must be a number"),
body("facilities")
.notEmpty()
.isArray()
.withMessage("Facilities must be an array"),
],
upload.array("imageFiles", 6),
async (req: Request, res: Response) => {
console.log("req body");
console.log(req.body);
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res
.status(400)
.json({ message: "Bad Request", errors: errors. array() });
}
try {
const files = req.files as Express.Multer.File[];
const promises = files.map(async (file) => {
const fileExt = mime.extension(file.mimetype);
console.log(file);
// const fileName = file.originalname;
if (!fileExt) {
throw new Error("Invalid file type");
}
const newFileName = `${Date.now()}`;
const params = {
Bucket: process.env.S3_BUCKET as string,
Key: `${Date.now()}.${fileExt}`,
Body: file.buffer,
ContentType: file.mimetype,
};
await client.send(new PutObjectCommand(params));
const link = `https://${process.env.S3_BUCKET_NAME}.${process.env.S3_REGION}.amazonaws.com/${newFileName}`;
return link;
});
const imageUrls = await Promise.all(promises);
const newHotel: HotelType = req.body; //some of the fields will already be filled by the req body
newHotel.imageUrls = imageUrls;
newHotel.lastUpdated = new Date();
newHotel.userId = req.userId; //this is taken from the auth token
//save the hotel to the database
const hotel = new Hotel(newHotel);
await hotel.save();
res.status(201).send(hotel); //201 is the status code for created
res.status(201).json({ message: "Images uploaded successfully" });
} catch (error) {
console.log("error creating hotel", error);
res.status(500).json({ message: "Internal server error" });
}
}
);
export default router;
现在,当我提交表单时,我收到以下错误:
错误请求-错误:
0: {type: "field", msg: "Name is required", path: "name", location: "body"}
1: {type: "field", msg: "City is required", path: "city", location: "body"}
2: {type: "field", msg: "Country is required", path: "country", location: "body"}
3: {type: "field", msg: "Description is required", path: "description", location: "body"}
4: {type: "field", msg: "Type is required", path: "type", location: "body"}
5: {type: "field", msg: "Invalid value", path: "pricePerNight", location: "body"}
6: {type: "field", msg: "Price per night must be a number", path: "pricePerNight", location: "body"}
7: {type: "field", msg: "Invalid value", path: "adultCapacity", location: "body"}
8: {type: "field", msg: "Adult capacity must be a number", path: "adultCapacity", location: "body"}
9: {type: "field", msg: "Invalid value", path: "childCapacity", location: "body"}
10: {type: "field", msg: "Child capacity must be a number", path: "childCapacity", location: "body"}
11: {type: "field", msg: "Invalid value", path: "starRating", location: "body"}
12: {type: "field", msg: "Star rating must be a number", path: "starRating", location: "body"}
13: {type: "field", msg: "Invalid value", path: "facilities", location: "body"}
14: {type: "field", msg: "Facilities must be an array", path: "facilities", location: "body"}
我的标题中的内容类型设置为application/json; charset=utf-8
.
这是请求的有效负载:
name: My Hotel
city: Iwdj
country: Pdihuf
description: poiuytrewqasdfghjkllllllllllllllllkmnbvcxz
type: hotel
pricePerNight: 7
starRating: 3
adultCapacity: 8
childCapacity: 7
facilities[0]: free parking
facilities[1]: swimming pool
imageFiles: (binary)
imageFiles: (binary)
我try 手动将内容类型设置为multipart/formdata
,但随后出现错误
多部分:找不到边界