node.js - res.sendFile(file) 和 express.static(file) 之间的异常差异
问题描述
我正在制作一个网络应用程序,我可以在其中上传一些我制作的 Three.js 虚拟现实项目并将它们提供给浏览器。
当我开始制作它时,我对我的 VR 文件夹进行了快速测试,看看是否可行。代码有效,因此我开始花费大量时间开发应用程序。我使用的代码如下:
app.use('/', express.static('/Users/virtuload-beta/backend/uploads/065fe1658b1374605f31d100eb1e7a1a1568654427336/Nancy_Collins_118226967_v2/'))
这工作得很好,浏览器渲染了我的 VR 场景。我还想确保文件可以动态提供(例如,用户单击要渲染的 VR 场景并使用指向 url 的 href 进行渲染),因此我执行了以下代码,它也可以正常工作:
const filepath = '065fe1658b1374605f31d100eb1e7a1a1568654427336/Nancy_Collins_118226967_v2/'
app.use('/', express.static(`/Users/virtuload-beta/backend/uploads/${filepath}`))
我现在基本上完成了应用程序,除了我有一个大问题,当我使用指定的 index.html 文件(您需要使用 res.sendFile)提供 VR 文件夹时,浏览器无法读取文件夹中的文件,我只是得到红色错误。
我的函数不再作为静态文件了,它从url中获取id,从mongodb中找到文件路径,如下:
const servepath = (req, res, next) => {
let id = req.params.id
Upload.findById(id)
.populate('Upload')
.select('relPath') //relPath = /folder/subfolder
.exec(function (err, upload) {
if (err) {
res.send(err)
console.log(err)
} else {
const dir = path.join(__dirname, '..', '../vr/uploads')
const filepath = `${upload.relPath}`
const fulldir = path.join(dir, filepath)
console.log(fulldir)
try {
res.sendFile('index.html', {root: `${fulldir}`});
}
}
catch (e) {
console.error(e)
}
// return next();
}
})
}
浏览器正在查找 html 文件,但无法用它解析 JS 文件:
GET http://localhost:3000/api/5d8b74be2af25086ab77fef7/js/three.js net::ERR_ABORTED 404(未找到)vr:21 GET http://localhost:3000/api/5d8b74be2af25086ab77fef7/js/OrbitControls.js网络: :ERR_ABORTED 404 (未找到) vr:22 GET http://localhost:3000/api/5d8b74be2af25086ab77fef7/js/GLTFLoader.js net::ERR_ABORTED 404 (未找到) vr:23 GET http://localhost:3000/api /5d8b74be2af25086ab77fef7/js/FBXLoader.js net::ERR_ABORTED 404(未找到)vr:24 GET http://localhost:3000/api/5d8b74be2af25086ab77fef7/js/inflate.min.js net::ERR_ABORTED 404(未找到)vr :25 GET http://localhost:3000/api/5d8b74be2af25086ab77fef7/js/WebGL.js net::ERR_ABORTED 404 (Not Found) vr:118 GEThttp://localhost:3000/api/5d8b74be2af25086ab77fef7/MainScene.js net::ERR_ABORTED 404(未找到)
当我将文件路径硬编码到我在此处指定的第一行代码(express.static)中时,vr 呈现完美...我尝试将文件作为静态文件提供,但您不能动态执行此操作,因此名称“静态”文件..有人知道为什么会这样吗?
我对标题了解不多,可能是我对标题缺乏了解吗?
解决方案
您的servepath
处理程序显然处理对GET /api/:id
. 当浏览器接收到index.html
匹配id
参数的内容时,它可能会找到表示为相对路径的引用,例如<script src="js/three.js">
. 要构建此资源的完全限定地址,它使用当前文件的位置。在你展示的情况下,这index.html
似乎是http://localhost:3000/api/5d8b74be2af25086ab77fef7
。
解决此问题的(相当)快速方法是:
- 静态公开您的项目(
express.static
在公用文件夹中显示所有上传内容,显然/vr/uploads
现在结束) - 然后,不是
index.html
直接提供 from ,而是/api/:id
将此路由用作到正确静态位置的重定向
像这样的东西:
// expose all uploads, under the URL http://localhost:3000/uploaded-projects/*
app.use(
'/uploaded-projects',
express.static(path.join(__dirname, '../../vr/uploads'))
);
// handler to match a Mongo project ID with a public path under /uploaded-projects
app.get(`/api/:id`, (req, res) => {
Upload.findById(req.params.id)
.populate('Upload')
.select('relPath')
.exec((err, data) => {
// ko: explicitly use an HTTP status otherwise it's 200
if (err) return res.status(500).send(err);
// ok: tell browser 302 + proper Location header
res.redirect(`/uploaded-projects/${data.relPath}/index.html`);
});
});
可能需要更多的努力,您可以更改您的前端,而不是使用项目列表中的 ID,而是使用relPath
(您可以将其提供给前端,因为您已经提供了 ID,并且它relPath
在里面Mongo 文档)和静态树的硬编码路径(在我的草图中/uploaded-projects
)。这将允许前端直接构建正确的 URL,从而避免联系服务器获取 302,您可以摆脱这/api/:id
条路线。
推荐阅读
- azure-data-factory - 将 GetMetaData ChildItems.name 直接插入表中而不使用任何迭代器-Azure 数据工厂
- python - 如何取消分组列表?
- azure - 使用 java 的 Azure 身份验证和授权
- database - Orocommerce 删除实体
- sql - 从 GPS 日志计算用户的距离和持续时间
- r - 在函数内部调用时,file.copy 不起作用
- elasticsearch - 这个弹性搜索查询有什么问题?
- python - 无法让熊猫正确导入
- tensorflow - keras 或 tensorflow 中的 Conv2D 层之后的 ConvLSTM2D
- r - 使用 mgcv 包中的 bam() 而不是 gam() 函数拟合随机效应模型时出错,R