You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js+Express实现带参数校验的隐式文件强制下载?

实现带参数校验的隐藏文件下载(Express)

核心实现方案(重定向隐藏链接)

用户访问/param?key=xxx时,后端先校验密钥合法性,通过后直接重定向到内部下载路由,但给下载路由加防护,禁止直接访问。

后端代码示例

const express = require('express');
const app = express();
const path = require('path');

// 密钥校验逻辑(替换成你的实际校验规则,比如从数据库查询)
const isValidKey = (key) => {
  return key === '23232323';
};

// 对外的参数校验入口
app.get('/param', (req, res) => {
  const { key } = req.query;
  if (!isValidKey(key)) {
    return res.status(403).send('无效访问密钥');
  }
  // 重定向到内部下载路由,用户看不到这个跳转地址
  res.redirect('/download/image.zip');
});

// 受保护的内部下载路由
app.get('/download/image.zip', (req, res) => {
  // 校验请求来源,只允许从/param路由重定向过来
  const referer = req.headers.referer;
  if (!referer || !referer.includes('your-domain.com/param')) {
    return res.status(403).send('禁止直接访问');
  }
  // 设置下载响应头,触发浏览器下载
  res.setHeader('Content-Disposition', 'attachment; filename="image.zip"');
  // 返回文件
  res.sendFile(path.resolve(__dirname, 'assets/image.zip'));
});

app.listen(3000, () => console.log('服务运行在3000端口'));

其他可选实现思路

思路1:直接流式返回文件(无跳转)

校验通过后不做重定向,直接将文件流返回给客户端,全程不会暴露任何下载链接:

app.get('/param', (req, res) => {
  const { key } = req.query;
  if (!isValidKey(key)) {
    return res.status(403).send('无效访问密钥');
  }
  // 直接设置下载头并返回文件
  res.setHeader('Content-Disposition', 'attachment; filename="image.zip"');
  res.sendFile(path.resolve(__dirname, 'assets/image.zip'));
});

这种方式更简洁,用户的请求始终停留在/param?key=xxx,完全看不到实际文件路径。

思路2:生成一次性临时令牌

如果需要支持有限次数/有效期的下载,可生成临时令牌:

  1. 校验密钥通过后,生成一个带有效期的临时令牌(存Redis或内存)
  2. 返回自动触发下载的页面,用令牌请求下载接口
  3. 下载接口校验令牌有效性,通过则返回文件
// 内存存储临时令牌(生产环境建议用Redis)
const tempTokens = new Map();

app.get('/param', (req, res) => {
  const { key } = req.query;
  if (!isValidKey(key)) {
    return res.status(403).send('无效访问密钥');
  }
  // 生成临时令牌,有效期10分钟
  const token = Math.random().toString(36).slice(2);
  tempTokens.set(token, { expires: Date.now() + 10 * 60 * 1000 });
  // 返回自动跳转的HTML
  res.send(`
    <html>
      <body>
        <script>window.location.href = '/download?token=${token}';</script>
      </body>
    </html>
  `);
});

app.get('/download', (req, res) => {
  const { token } = req.query;
  const tokenData = tempTokens.get(token);
  // 校验令牌有效性
  if (!tokenData || tokenData.expires < Date.now()) {
    tempTokens.delete(token);
    return res.status(403).send('令牌无效或已过期');
  }
  tempTokens.delete(token); // 令牌一次性使用
  res.setHeader('Content-Disposition', 'attachment; filename="image.zip"');
  res.sendFile(path.resolve(__dirname, 'assets/image.zip'));
});

生产环境注意事项

  • 密钥校验逻辑要严谨,避免硬编码,建议从数据库或配置中心读取有效密钥
  • 大文件下载建议用res.download()或流式传输,防止内存溢出
  • 内部路由的防护逻辑要完善,避免用户通过猜测路径直接访问文件

内容的提问来源于stack exchange,提问作者kar psk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:55:20