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

基于PHP+MySQL实现文件临时有效链接的技术问询

PHP+MySQL实现文件临时链接系统方案

1. 数据库表设计

首先创建存储临时链接信息的表,关联用户、文件与有效期:

CREATE TABLE `temp_file_links` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `user_id` INT UNSIGNED NOT NULL, -- 关联你的用户表ID
  `file_path` VARCHAR(255) NOT NULL, -- 文件真实存储路径(建议放在web根目录外)
  `token` VARCHAR(64) NOT NULL UNIQUE, -- 临时链接唯一标识
  `expire_at` DATETIME NOT NULL, -- 过期时间
  `is_used` TINYINT(1) DEFAULT 0, -- 可选:标记是否已被访问
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) -- 替换为你的用户表名
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 生成临时链接的逻辑

用户申请链接时,生成安全唯一的token,计算过期时间并存入数据库:

<?php
// 假设已登录,获取当前用户ID
$userId = $_SESSION['user_id'];
$filePath = '/var/www/secure_files/report.pdf'; // 替换为实际文件路径(web根外)
$expireMinutes = 120; // 用户指定的有效期,比如120分钟

// 生成64位安全随机token
$token = bin2hex(random_bytes(32));

// 计算过期时间
$expireAt = date('Y-m-d H:i:s', time() + ($expireMinutes * 60));

// 插入数据库
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass');
$stmt = $pdo->prepare("INSERT INTO temp_file_links (user_id, file_path, token, expire_at) VALUES (?, ?, ?, ?)");
$stmt->execute([$userId, $filePath, $token, $expireAt]);

// 返回给用户的临时链接
$tempLink = "https://yourdomain.com/get_file.php?token=" . $token;
echo "临时文件链接:" . $tempLink;
?>

3. 验证链接并返回文件的逻辑

创建get_file.php处理链接请求,验证有效性后返回文件:

<?php
if (!isset($_GET['token'])) {
    http_response_code(404);
    exit("无效链接");
}

$token = $_GET['token'];
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass');

// 查询有效链接(未过期、未被使用)
$stmt = $pdo->prepare("SELECT * FROM temp_file_links WHERE token = ? AND expire_at > NOW() AND is_used = 0");
$stmt->execute([$token]);
$linkInfo = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$linkInfo) {
    http_response_code(404);
    exit("链接已过期或无效");
}

// 标记链接为已使用(可选,按需决定是否允许多次访问)
$stmt = $pdo->prepare("UPDATE temp_file_links SET is_used = 1 WHERE token = ?");
$stmt->execute([$token]);

// 返回文件
$filePath = $linkInfo['file_path'];
if (!file_exists($filePath)) {
    http_response_code(404);
    exit("文件不存在");
}

// 设置响应头
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Content-Length: ' . filesize($filePath));

// 输出文件内容
readfile($filePath);
exit;
?>

4. 过期链接的清理

避免数据库冗余,定期清理过期记录:

  • Cron定时任务方案
    编写清理脚本clean_expired.php:

    <?php
    $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass');
    $stmt = $pdo->prepare("DELETE FROM temp_file_links WHERE expire_at < NOW()");
    $stmt->execute();
    ?>
    

    在服务器Cron中添加每日凌晨执行的任务:

    0 0 * * * /usr/bin/php /var/www/scripts/clean_expired.php
    
  • MySQL事件调度器方案
    开启调度后创建定时清理事件:

    SET GLOBAL event_scheduler = ON;
    CREATE EVENT clean_expired_links
    ON SCHEDULE EVERY 1 DAY
    STARTS CURRENT_DATE + INTERVAL 1 DAY
    DO
      DELETE FROM temp_file_links WHERE expire_at < NOW();
    

5. 安全与优化建议

  • 文件务必存在于web根目录以外,禁止直接URL访问,必须通过PHP中转验证。
  • 用random_bytes()生成token,避免uniqid()这类可预测的字符串。
  • 可限制单个用户生成的临时链接数量,或单链接的访问次数。
  • 可选添加accessed_at字段记录首次访问时间,便于排查问题。
  • 生成链接前验证用户对目标文件的访问权限,防止越权操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:48:35