【问题标题】:Trigger an action when a certain file URL is downloaded下载特定文件 URL 时触发操作
【发布时间】:2019-04-26 21:17:46
【问题描述】:

我想在 Apache 检测到某个文件 URL 已开始下载时触发​​操作(或:成功下载)。

示例:当客户端下载https://example.com/download/token_A6FZ523/myfile.zip时,对SQLite数据库执行以下查询:

INSERT INTO downloads(date, tokenID) VALUES(CURRENT_TIMESTAMP, "A6FZ523");

用法:然后,在 PHP Dashboard 中,我可以检查谁下载了交付的文件。

我可以这样做:

  • 每分钟在服务器上运行一个脚本,
  • 解析 Apache 日志 /var/log/apache2/other_vhosts_access.log 以搜索模式 download/token_.*/myfile.zip

  • 在这种情况下执行INSERT INTO查询

这似乎相当复杂,而且必须每分钟运行脚本这一事实并不是一个好的解决方案。

要求 Apache 将信息保存到 SQLite 数据库有什么好的解决方案“与下载令牌 A6FZ523 相关的文件已被客户端下载。”? 还是应该改用 PHP?

【问题讨论】:

  • “已下载”是什么意思?你怎么知道他们没有取消下载?
  • @Mike'Pomax'Kamermans “用户开始下载”的信息足以满足我的目的(我现在不需要知道它是否成功)。
  • 恭喜:您回答了自己的问题。当用户通过单击下载链接在您的页面上开始下载时,将分析事件发送到您正在使用的任何服务(您自己的或第三方),通过向下载链接添加点击侦听器的客户端或服务器- 在服务器端注册一个文件 URL 刚刚被击中。
  • @Mike'Pomax'Kamermans 下载链接通常在电子邮件中(它甚至可以是纯文本电子邮件,没有 HTML)。我无法在电子邮件中添加 Javascript 事件侦听器来检测链接何时被点击(即使我可以,这也不是一个优雅的解决方案)。我真的很想检测文件何时开始直接下载到服务器上。如何做到这一点?

标签: php apache sqlite download


【解决方案1】:

我认为您的问题在于您直接获取存储在服务器上的文件,而不是使用 PHP 以编程方式“提供”该文件。这不是您使用此方法遇到的第一个问题,您也无法检查安全性或从外部文件存储中获取文件(一般来说,这些天您不会将文件直接存储在 Web 服务器上!)。

但是,一旦你知道如何做就很简单:)

首先,让我们将下载文件的 URL 更改为 https://example.com/download.php?token=A6FZ523

因此,我们将 GET 变量发送到名为“download.php”的 php 脚本。在该脚本中,您将拥有如下内容:

<?php 
$token = $_GET['token'];

// Get the information about the file from the DB, something like:
// SELECT filename, size, path FROM files WHERE token = $token;
// Giving you $filename, $size and $path

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $filename); 
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $size);

echo file_get_contents($path);

// This will be on a completed download
// INSERT INTO downloads(date, tokenID) VALUES(CURRENT_TIMESTAMP, $token);
?>

当调用 download.php 文件时,会获取令牌并将其与数据库中的文件信息匹配。然后,您设置标题,它基本上告诉浏览器“这是一个文件”,您的浏览器通过正常执行文件下载来相应地响应。然后,您将文件的内容读给用户。完成后,您可以通过另一个 DB 调用记录下载。

要说的一件大事是,这个脚本(显然是写入了 DB 调用)应该为您做最基本的工作,但根据您的使用场景,还有更多内容需要添加。想想安全性、输入验证、存储文件和发送 MIME 类型标头的位置。

希望这应该为您指明正确的方向:)

【讨论】:

  • 感谢您的回答。两件小事:1)如果我仍然想给客户端https://example.com/download/token_A6FZ523/myfile.zip,而不是/download.php?token=A6FZ523,你会使用哪种Apache URL 重写规则? 2)我很乐意复制/粘贴所有这些标题,但是您是否有一个源/文档显示这些标题中的哪些是真正重要/强制性的,哪些是可选的等等,以确保不会忘记任何东西。
  • 老实说,如果可能的话,我会更改下载 URL!我确信使用 Apache 重写规则是可能的,但我不是他们的专家(/讨厌他们!)所以可能最好开始另一个问题。 Http 标头(就是那些)符合 html/浏览器标准;它们不是 PHP 的东西。例如,有关缓存控制标头的文档,请参阅 this。我知道这组标头使我测试过的所有浏览器都能正确响应是我诚实的回答...
  • 这是一个有用的答案。正如其他一些答案所说,请务必完成文件请求的服务器端身份验证。不要让客户端访问目录或任何服务器端身份验证数据。使用令牌是执行此操作的好方法,但您需要确保在提供文件之前进行用户身份验证并确认权限。
【解决方案2】:

如果您有权访问服务器并有权安装 Thins,您可以添加 mod_log_sql 并让 apache 将日志直接保存到数据库表中(它甚至会为您解析信息),您可以在仪表板中进行简单的查询。这里的“东西”表明您需要获取下载器的名称,因此您应该将该“tokenID”添加到您的 URL 并设置 Apache 以在 tokenID 不存在时拒绝该 url。您需要在日志中从 url 解析 tokenID。

【讨论】:

  • 感谢您的回答!您是否可以编辑以包含一些代码示例以更容易测试?提前谢谢你。
  • 看看这个链接colekcolek.com/2012/03/12/…
猜你喜欢
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-22
  • 1970-01-01
相关资源
最近更新 更多