【问题标题】:Unusual differences between res.sendFile(file) and express.static(file)res.sendFile(file) 和 express.static(file) 之间的异常差异
【发布时间】:2019-09-25 16:39:32
【问题描述】:

我正在制作一个网络应用程序,我可以在其中上传一些我制作的 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 net::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(未找到) vr:118 GET http://localhost:3000/api/5d8b74be2af25086ab77fef7/MainScene.js net::ERR_ABORTED 404(未找到)

当我将文件路径硬编码到我在此处指定的第一行代码 (express.static) 中时,vr 呈现完美...我尝试将文件作为静态文件提供,但您无法动态执行此操作,因此名称为“静态”文件..有人知道为什么会这样吗?

我对标头了解不多,可能是我对标头缺乏了解吗??

【问题讨论】:

    标签: node.js express static


    【解决方案1】:

    您的servepath 处理程序显然处理了对GET /api/:id 的请求。当浏览器接收到与id 参数匹配的index.html 的内容时,它可能会找到表示为相对 路径的引用,例如<script src="js/three.js">。为了构建此资源的完全限定地址,它使用当前文件的位置。其中,在您显示的index.html 的情况下,似乎是http://localhost:3000/api/5d8b74be2af25086ab77fef7

    解决此问题的一种(相当)快速的方法是:

    • 静态公开您的项目(公共文件夹中的express.static 用于您所有上传的内容,现在显然以/vr/uploads 结尾)
    • 然后,不要直接从/api/:id 提供index.html,而是将此路由用作到正确静态位置的重定向

    类似的东西:

    // 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 路由。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-19
      • 2016-01-24
      • 2014-01-08
      • 2015-10-04
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 2018-01-06
      相关资源
      最近更新 更多