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

如何用Node.js/Express实现带有效期的下载链接(含前后端代码)

Node.js + Express 限时失效下载链接实现方案

实现逻辑

通过JWT(JSON Web Token)生成带过期时间的签名下载链接,请求下载时校验签名有效性和过期状态,无需额外存储数据即可实现链接限时生效,适合小型项目快速落地。

依赖安装

首先在项目根目录执行以下命令安装所需依赖:

npm install express jsonwebtoken cors

后端完整代码

const express = require('express');
const jwt = require('jsonwebtoken');
const path = require('path');
const cors = require('cors');
const fs = require('fs');

const app = express();
// 前后端分离场景下配置跨域
app.use(cors());
// 解析POST请求的JSON参数
app.use(express.json());

// 签名密钥 *生产环境请务必存储在环境变量中,禁止硬编码泄露*
const SECRET_KEY = 'replace_this_with_your_own_secret_key';
// 可下载文件存放目录,需提前在项目根目录创建该文件夹
const DOWNLOAD_DIR = path.join(__dirname, 'download-files');

// 生成限时下载链接接口
app.post('/generate-download-link', (req, res) => {
  const { fileName, expireSeconds = 3600 } = req.body;

  // 校验文件是否存在,过滤无效请求
  const targetFilePath = path.join(DOWNLOAD_DIR, fileName);
  if (!fs.existsSync(targetFilePath)) {
    return res.status(404).json({ msg: '请求的文件不存在' });
  }

  // 校验文件名合法性,防止路径遍历漏洞
  if (fileName.includes('..') || path.resolve(targetFilePath) !== path.join(DOWNLOAD_DIR, path.basename(fileName))) {
    return res.status(403).json({ msg: '非法的文件名' });
  }

  // 生成带过期时间的签名token
  const downloadToken = jwt.sign(
    { fileName },
    SECRET_KEY,
    { expiresIn: expireSeconds }
  );

  // 拼接完整下载链接返回
  const downloadLink = `${req.protocol}://${req.get('host')}/download?token=${downloadToken}`;
  res.json({
    downloadLink,
    expireTime: new Date(Date.now() + expireSeconds * 1000).toLocaleString()
  });
});

// 下载处理接口
app.get('/download', (req, res) => {
  const { token } = req.query;
  if (!token) {
    return res.status(400).send('无效的下载链接');
  }

  try {
    // 校验token有效性,过期/签名错误都会抛出异常
    const decoded = jwt.verify(token, SECRET_KEY);
    const targetFilePath = path.join(DOWNLOAD_DIR, decoded.fileName);

    // 二次校验文件存在
    if (!fs.existsSync(targetFilePath)) {
      return res.status(404).send('文件不存在');
    }

    // 触发文件下载
    res.download(targetFilePath, decoded.fileName);
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(410).send('该下载链接已过期');
    }
    res.status(403).send('无效的下载链接');
  }
});

// 启动服务
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`服务已启动,访问地址:http://localhost:${PORT}`);
});

前端示例代码(原生HTML+JS,无框架依赖)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>限时下载链接生成工具</title>
</head>
<body>
  <div style="margin: 20px;">
    <div style="margin-bottom: 10px;">
      <label>文件名:</label>
      <input type="text" id="fileNameInput" value="test.pdf" placeholder="请输入要下载的文件名">
    </div>
    <div style="margin-bottom: 10px;">
      <label>链接有效期(秒):</label>
      <input type="number" id="expireInput" value="60" min="10">
    </div>
    <button id="generateBtn">生成下载链接</button>
    <div id="resultContainer" style="margin-top: 20px;"></div>
  </div>

  <script>
    const generateBtn = document.getElementById('generateBtn');
    const resultContainer = document.getElementById('resultContainer');

    generateBtn.addEventListener('click', async () => {
      const fileName = document.getElementById('fileNameInput').value.trim();
      const expireSeconds = Number(document.getElementById('expireInput').value);

      if (!fileName) {
        resultContainer.innerHTML = '<p style="color: red;">请输入文件名</p>';
        return;
      }

      try {
        const resp = await fetch('http://localhost:3000/generate-download-link', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ fileName, expireSeconds })
        });
        const data = await resp.json();

        if (resp.ok) {
          resultContainer.innerHTML = `
            <p>✅ 下载链接生成成功,有效期至:${data.expireTime}</p>
            <a href="${data.downloadLink}" target="_blank">点击直接下载</a>
            <p style="word-break: break-all; margin-top: 10px;">链接地址:${data.downloadLink}</p>
          `;
        } else {
          resultContainer.innerHTML = `<p style="color: red;">❌ 生成失败:${data.msg}</p>`;
        }
      } catch (e) {
        resultContainer.innerHTML = '<p style="color: red;">❌ 请求失败,请检查后端服务是否正常启动</p>';
      }
    });
  </script>
</body>
</html>

使用步骤

  1. 在项目根目录创建download-files文件夹,将需要提供下载的文件放到该目录下
  2. 运行后端服务:node server.js(假设后端代码保存为server.js)
  3. 直接打开前端HTML文件,输入对应的文件名和有效期,点击生成链接即可测试

注意事项

  • 生成链接的有效期最长不要超过7天,避免链接泄露后被长期滥用
  • 生产环境建议添加接口请求频率限制,防止接口被恶意刷量
  • 如果需要支持手动撤销下载链接,可以将生成的token、过期时间、状态存储到数据库,下载时额外校验token是否已被禁用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:27:03