返回
MongoDB 中添加新对象后,如何更改之前添加的对象的图像名称?
javascript
2024-03-16 07:34:17
MongoDB: 添加新对象后更改之前添加的对象
引言
在构建全栈应用程序时,有时会出现令人困惑的问题。例如,在一个使用 AWS S3 和 MongoDB 的 React 应用程序中,向前端添加新食谱时,后端创建的 rndImageName
有时会更改。这篇文章将深入探讨这一问题,并提供逐步解决问题的指南。
问题根源
该问题的根源在于未正确生成和使用唯一的 rndImageName
。在 multer.js
中,用于生成图像名称的函数是全局变量,这意味着它会在处理不同请求时被覆盖。这导致为不同的食谱分配了相同的图像名称。
解决方法
为了解决这一问题,我们采取了以下步骤:
- 创建唯一的随机图像名称: 使用
uuid
包在multer.js
中生成唯一的随机图像名称。 - 使用随机图像名称上传到 S3: 使用
rndImageName
作为 S3 对象的名称,确保每个图像都有不同的名称。 - 将图像名称存储在 MongoDB 中: 将
rndImageName
存储在 MongoDB 文档的imageName
字段中,以便将来使用。 - 避免使用全局变量: 确保
rndImageName
是一个局部变量,而不是全局变量,以防止在处理不同请求时覆盖相同的图像名称。
实现细节
multer.js
const { v4: uuidv4 } = require('uuid');
awsRouter.post('/recipeImages', upload.single('file'), async (req, res) => {
const buffer = await sharp(req.file.buffer).resize({ height: 1920, width: 1080, fit: 'contain' }).toBuffer()
const rndImageName = uuidv4();
const params = {
Bucket: bucketName,
Key: 'recipeImages/' + rndImageName,
Body: buffer,
ContentType: req.file.mimetype
}
const command = new PutObjectCommand(params)
await s3.send(command)
})
recipes.js
recipesRouter.post('/', async (request, response, next) => {
const body = request.body
const decodedToken = jwt.verify(getTokenFrom(request), process.env.SECRET)
if (!decodedToken.id) {
return response.status(401).json({ error: 'token invalid' })
}
const user = await User.findById(decodedToken.id)
const recipe = new Recipe({
// ...
imageName: rndImageName,
// ...
})
const savedRecipe = await recipe.save()
user.recipes = user.recipes.concat(savedRecipe._id)
await user.save()
})
结论
通过这些更改,我们可以确保每个食谱都使用唯一的 rndImageName
,从而避免了 MongoDB 中名称冲突的问题。这使我们能够为特定食谱创建 SignedURL,并保持图像名称的正确性。
常见问题解答
-
为什么会出现名称冲突的问题?
- 由于使用全局变量生成
rndImageName
,它在处理不同请求时被覆盖,导致为不同的食谱分配了相同的图像名称。
- 由于使用全局变量生成
-
如何避免名称冲突?
- 使用
uuid
包生成唯一的随机图像名称并将其作为局部变量存储。
- 使用
-
使用
rndImageName
有什么好处?- 避免名称冲突,允许为每个食谱创建唯一的 SignedURL,从而确保图像名称的正确性。
-
实现这些更改会对性能产生什么影响?
- 生成和存储唯一的
rndImageName
可能对性能产生轻微的影响,但它是避免名称冲突并确保数据完整性的必要权衡。
- 生成和存储唯一的
-
这些更改适用于其他需要处理文件上传的应用程序吗?
- 是的,这些更改可以应用于需要处理文件上传的任何应用程序,不仅限于 MongoDB 和 AWS S3。