Scenario
前端基本上是一个 React Native (Expo) 应用程序,用户可以在其中发布报告 - 这包括拍摄多张照片并填写一些详细信息。
后端只是node.js,带有 Express 和 Multer。
Problem
我使用 Axios 通过以下方式发送图像和表单数据FormData()
,但是在服务器端,req.body 和 req.files 不包含任何内容.
这里的一件事是,通过 POSTMAN 发送相同的数据工作完全正常,图像存储到 S3 中,表单详细信息存储在数据库中。这是通过应用程序/模拟器不起作用。
我尝试删除“multipart/form-data”标头,这是 console.log(req.body) 的输出(req.files 显示未定义):
{
_parts: [
[ 'userId', '1f400069-07d0-4277-a875-cbb2807750c5' ],
[
'location',
'some location'
],
[ 'description', 'Aaaaa' ],
[ 'report-images', [Object] ]
]
}
当我把“multipart/form-data”标题放回去时,这个输出甚至没有出现。
我做了什么
过去几个小时我一直在寻找解决方案,但没有一个有效。这些解决方案是:
- 在“multipart/form-data”标题后面添加边界
- 将类型设置为“image/jpeg”
- 将文件 uri 修剪为“file://”
但它们都不起作用
这是我的代码:
React Native 前端(博览会)
const submitReport = async () => {
setShowLoading(true);
// Validate details (location & images)
if (location === "") {
setShowLoading(false);
showToast(7002);
return;
}
if (images.length === 0) {
setShowLoading(false);
showToast(7004);
return;
}
try {
const formData = new FormData();
formData.append("userId", user.userId);
formData.append("location", location);
formData.append("description", description);
images.forEach(img => {
const trimmedURI = (Platform.OS === "android") ? img.uri : img.uri.replace("file://", "");
const fileName = trimmedURI.split("/").pop();
const media = {
name: fileName,
height: img.height,
width: img.width,
type: mime.getType(trimmedURI),
uri: trimmedURI
};
formData.append("report-images", media);
});
const response = await axios.post(`http://<my-ip-address>:3003/api/report/submit`, formData, { headers: { 'Content-Type': "application/x-www-form-urlencoded" } });
console.log(response)
setShowLoading(false);
}
catch (error) {
console.log(error);
setShowLoading(false);
showToast(9999);
}
};
Backend
// Multer-S3 Configuration
const upload = multer({
storage: multerS3({
s3: s3,
bucket: process.env.AWS_S3_BUCKET_NAME,
contentType: (req, file, callback) => {
callback(null, file.mimetype);
},
metadata: (req, file, callback) => {
callback(null, { fieldName: file.fieldname });
},
key: (req, file, callback) => {
callback(null, `${process.env.AWS_S3_REPORT_IMAGES_OBJECT_PATH}${req.body.userId}/${new Date().getTime().toString()}-${file.originalname}`)
}
}),
fileFilter: (req, file, callback) => {
// Check if file formats are valid
if (file.mimetype === "image/png" || file.mimetype === "image/jpg" || file.mimetype === "image/jpeg") {
callback(null, true);
}
else {
callback(null, false);
return callback(new Error("Image File Type Unsupported"));
}
},
});
router.post("/submit", upload.array("report-images", 3), async (req, res) => {
try {
// req -> FormData consisting of userId, location & description
// multer-s3 library will handle the uploading to S3 - no need to code here
// Details of files uploaded on S3 (Bucket, Key, etc.) will be displayed in req.files
// Analyze from Rekognition
//Add to Database code blablabla
if (result.success === true) {
res.status(200).send({ message: result.data });
}
else if (result.success === false) {
res.status(404).send({ error: ERROR_MESSAGE });
}
}
catch (error) {
console.log(error);
res.status(404).send({ error: ERROR_MESSAGE });
}
});
我不确定这是 Axios 的问题还是我这边的问题。
这个项目是我的最后一年项目。