【发布时间】:2021-07-04 23:17:33
【问题描述】:
我在我的应用程序中有一个正在工作的函数,它允许我提交一个带有图像的表单,然后使用 Multer 将图像存储在一个文件中,并将一个 URL 上传到我的 Postgres 数据库。当我将文件返回到前端时,我只剩下与图像相关的文件名,但我不知道如何添加文件路径以便显示图像。
在插入数据库时是否应该添加前缀文件路径?或者,如果我在前端显示完整的文件路径,是否存在安全问题。显然我知道我的前端和后端应该解耦并独立运行。我也可以为后端之外的图像创建一个单独的文件,但我不确定这是否是推荐的过程。如果这是在专业环境中,它只会由 Google Cloud、AWS 等公司处理,所以我不确定在这种情况下是否完全可以遵循解耦过程。
我在一些类似的情况下看到了 process-cwd,但我不确定这是否是我需要做的。我可以在前端 React 组件中硬编码文件路径,然后使用末尾有文件名的 redux 数据吗?
我的照片文件名存储在我的 Redux 商店中,但我不知道从那里去。该图像目前在我的后端/资产文件中。
将图像插入 Postgres 的 API。
exports.createDiveSpot = async (req, res) => {
const fileNameWithExtension = `${req.file.filename}-${req.file.originalname}`
const newPath = `./assets/diveSpot/${fileNameWithExtension}`
fs.rename(req.file.path, newPath, function (err) {
if (err) {
console.log(err)
res.send(500)
}
console.log(req.body)
diveSpot.create({
diveLocation: req.body.diveLocation,
diveRegionID: req.body.diveRegionID,
diveSpotTypeID: req.body.diveSpotTypeID,
diveSpotDescription: req.body.diveSpotDescription,
photos: fileNameWithExtension,
}).then((data) => {
res.send(data)
})
更新
在下面的方法中。我注意到我可以在“const fileNameWithExtension”行中轻松输入文件名。我可以在前端输入公共文件的 url,还是应该在我的后端使用 express 公开文件。我是否应该将后端的文件再次放入前端,因为它在技术上已经从前端提交,然后 multer 会将其移到前端?
我在下面包含了我最新的错误消息。
exports.createArticle = async (req, res) => {
console.log(req.body)
const fileNameWithExtension = "../home/backend/assets/article/"`${req.file.filename}-${req.file.originalname}`
const newPath = `./assets/article/${fileNameWithExtension}`
console.log(req.body)
fs.rename(req.file.path, newPath, function (err) {
if (err) {
console.log(err)
res.send(500)
}
article.create({
articleTitle: req.body.articleTitle,
articleContent: req.body.articleContent,
userID: req.body.userID,
articleTypeID: req.body.articleTypeID,
photos: fileNameWithExtension,
}).then((data) => {
res.send(data)
})
.catch((err) => {
res.status(500).send({
message: err.message || 'Some error occurred while creating the post.',
})
})
}
)}
错误信息
[Error: ENOENT: no such file or directory, rename 'C:\Users\James Greene\WebstormProjects\softwaredevproject\SustainableScuba\backend\assets\article\678c78
193bb73ab287bbb6b644a0c86e' -> 'C:\Users\James Greene\WebstormProjects\softwaredevproject\WebApp\sustainable-scuba-web-app\public\article\678c78193bb73ab28
7bbb6b644a0c86e-sharkfeat.jpg'] {
errno: -4058,
code: 'ENOENT',
syscall: 'rename',
path: '...\\SustainableScuba\\backend\\assets\\article\\678c78193bb73ab287bbb6b644a0c86e',
dest: '...\\sustainable-scuba-web-app\\public\\article\\678c78193bb73ab287bbb6b644a0c86
e-sharkfeat.jpg'
}
express deprecated res.send(status): Use res.sendStatus(status) instead controllers\article.controller.js:15:21
Executing (default): INSERT INTO "articles" ("articleID","articleTitle","articleContent","photos","userID","articleTypeID") VALUES (DEFAULT,$1,$2,$3,$4,$5)
RETURNING *;
Unhandled rejection Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:485:11)
at ServerResponse.header (...\backend\node_modules\express\lib\response.js:771:1
0)
它正在 Redux 的前端渲染并在商店中。我正在尝试在下面的卡片组件上显示图像。
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={articleList.articleTitle}
subheader={userID}/>
<CardMedia
id="Photos"
className={classes.media}
image={articleList.photos}
title="Dive Photos"/>
<CardContent>
<Typography className="Type" id="Type" variant="body2" color="textSecondary" component="p">
{articleType}
【问题讨论】:
-
您是否尝试过将保存图片的文件夹设置为公开方式?如果在前端您从服务器获得“someimage.jpg”作为响应,则应该很容易将 src 设置为 您的后端地址/带有图像的公共文件夹/图像名称
-
我会将图像的 URL 存储在数据库中的某个位置,然后将其返回给客户端。客户端需要以一种或另一种方式显示图像的完整 URL,因此这不是安全问题。这还允许您更改将来存储媒体的位置,而无需更改应用程序代码。例如,您可以从自己托管媒体文件切换到内容交付网络。在这种情况下,您的应用程序会在没有更新的情况下中断,因为它只有文件名而不是图像的完整 URL。
-
如何将前缀添加到文件名中,以便图像可以位于前端?我认为这应该在后端的控制器 API 上。
-
上传的图片有安全隐患吗?它们可以像博客内容一样在公共文件夹中发布,还是只需要像个人照片一样向授权用户显示?
-
该错误表示较旧的错误处理代码,因此它可能隐藏了真正的问题:
express deprecated res.send(status): Use res.sendStatus(status) instead。听起来你的上传工作正常,你能说明你是如何将图像返回到前端进行渲染的吗?
标签: node.js reactjs express redux