• PHP每天自动更新静态文件下载地址,防盗链


    在网站中的文件下载一般会有2种方式,永久链接和程序动态输出。

    • 静态链接下载的好处是可以通过客户端软件进行断点续传,但是缺点是无法保护程序的安全性,无法控制客户端的权限问题。
    • 程 序动态输出则与静态链接下载刚好相反,可以控制权限的问题,但是无法保证客户端下载断点续传的问题,虽然大部分浏览器也支持动态程序输出文件的断点续传, 但是需要客户端一直保持在有权限的状态下。如果客户端的Session关闭时权限丢失,那么下载就会结束掉,需要重新验证权限并重新开始下载。

    下载文件的问题与解决方案

    当下载的文件过大,或者网络带宽不够高的情况下,只有静态链接下载才会让下载的用户满意。

    但是你不想客户把这个下载的链接地址传播开来,如果你在短时间内把文件名或者目录名改了,又会直接影响到用户的下载。

    所以最终我们需要在有限的时间内能满足正在下载的用户,又能修改文件的访问路径。

    假设一个2G的文件,下载时间在几个小时到2天的范围内能完成下载。那么我们就应该让最开始下载的那个链接至少保持2天,在第3天的时候删除它,这样我们就想到了数据结构中的队列来解决这个问题,请看下图:

    下载文件随机URL队列

    明白这个队列的原理,我们接下来就在不需要数据库的情况下建立一个txt文件来存放3个随机的URL加上一个第四个计算好的URL。然后让这个程序在cronjob的中运行,可以在每天的晚上00:00运行,让队列移动一格。

    PHP实现队列

    文 件1为存放的队列,queue.txt格式为8个随机字符串是从ABCDEFFGHHIJKLMNOPQRSTUVWXYZ0123456789中随机抽 取的,作为文件的存放目录。目录有一个下划线作为分隔,1代表文件夹存在并有用户在下载,0代表文件夹没有在使用中,将在队列移动时把替换到第一个文件 夹。因为文件夹改变了,文件下载的URL也随之改变了。

    下面是这个queue.txt每天的变化情况。

    第一天

    第二天

    第三天

    第四天

    AAAAAAAA_1

    BBBBBBBB_1

    CCCCCCCC_1

    DDDDDDDD_1

    BBBBBBBB_1

    CCCCCCCC_1

    DDDDDDDD_1

    EEEEEEEE_1

    CCCCCCCC_1

    DDDDDDDD_1

    EEEEEEEE_1

    FFFFFFFF_1

    DDDDDDDD_0

    EEEEEEEE_0

    FFFFFFFF_0

    GGGGGGGG_0

    每天自动运行的PHP程序auto_change_folder.php,它的作用是将第四个文件夹替换到第一个文件夹。

    <?php
        $length = 8;
        $filename = ‘queue.txt’;
        $root = dirname(__FILE__);
        $handle = fopen($filename, "r");
        $folders = $codes = array();
        while (!feof($handle)) {
          $buffer = fgets($handle);
          if ($buffer) {
            $folder = explode(‘_’, trim($buffer));
            $folders[] = $folder;
            $codes[] = $folder[0];
          }
        }
        fclose($handle);
        $count = 0;
        $need_folder = $pre_folder = $code = ”;
        foreach($folders as $k=>$f) {
          if($f[1] && is_dir($f[0]) && file_exists($f[0].’/file.zip’)) {
            $count++;
          }
          elseif($f[1] && !(is_dir($f[0]) && file_exists($f[0].’/file.zip’))) {
            unset($folders[$k]);
          }
          elseif($f[1] == 0) {
            $need_folder = $f[0];
            $folders[$k][1] = 1;
            break;
          }
        }
        $pre_folder = $folders[$count-1][0];
        if($count == 3) {
          $remove_folder = array_shift($folders);
          echo $remove_folder[0], " ", $pre_folder." ".$need_folder." ";
          if(@rename($root.’/’.$remove_folder[0], $root.’/’.$need_folder)) {
           
          }
          else {
            die("Rename folder failed.");
          }
        }
        else {
          die("Folder not right.");
        }
    
        $alpha = ‘ABCDEFFGHHIJKLMNOPQRSTUVWXYZ0123456789′;
        $allowed_chars = str_split($alpha);
        do {
          for ($i = 0; $i < $length; $i++) {
            $code .= $allowed_chars[array_rand($allowed_chars)];
          }
        } while(in_array($code, $codes));
        array_push($folders, array($code, 0));
        $output = ”;
        foreach($folders as $k=>$f) {
          $output .= implode(‘_’, $f);
          if($f[1]) {
            $output .= "
    ";
          }
        }
        file_put_contents($filename, $output);
    ?>
    

    把这个auto_change_folder.php文件放入cronjob中运行。

    0    0    *    *    *    wget -O /dev/null  http://blog.lixiphp.com/files/big/auto_change_folder.php

    PHP文件获取最新的文件下载地址

    当然静态地址不可能每天都手动去获取,当然要通过PHP自动获取,这样这个地址可以随便显示出来让用户下载。

     

    我们把这个文件命名为auto_download_here.php,当然这个程序要去判断最终目标文件是否存在。

    <?php
        $filename = ‘queue.txt’;
        $root = dirname(__FILE__);
        $handle = fopen($filename, "r");
        $folders = $codes = array();
        $count = 0;
        $need_folder = ”;
        while (!feof($handle)) {
          $buffer = fgets($handle);
          if ($buffer) {
            $folder = explode(‘_’, trim($buffer));
            if($folder[1] && is_dir($folder[0]) && file_exists($folder[0].’/file.zip’)) {
              $count++;
            }
            elseif($folder[1] && !(is_dir($folder[0]) && file_exists($folder[0].’/file.zip’))) {
              unset($folder);
            }
            elseif($folder[1] == 0) {
              $need_folder = $f[0];
              break;
            }
            $folders[] = $folder;
          }
        }
        fclose($handle);
    
        $pre_folder = $folders[$count-1][0];
        header("Location: $pre_folder/file.zip");
    
    ?>
    

    完了,我们进入演示环节吧!

    自动下载地址切换下载演示

    文件下载地址:http://demo.lixiphp.com/switch_download/auto_download_here.php

    每天自动更新程序:http://demo.lixiphp.com/switch_download/auto_change_folder.php

    队列查看地址:http://demo.lixiphp.com/switch_download/queue.txt

     

    备注:

    • 如果想更新文件夹长度,可以修改auto_change_folder.php第二行,$length = 8; 默认长度是8;
    • 文件保留天数与队列长度有关;
    • 文件夹丢失后,队列将无法自动运行;
    • 文件夹的权限需要为0777;
     
  • 相关阅读:
    立一个flag。
    详解 fcntl 记录上锁。
    [转] 虚拟机中生成与物理机的共享文档。
    Shell实现1.0
    深剖malloc、new
    由命名管道的实现联想到 read 和 fread 的区别。
    僵尸进程与孤儿进程。
    Vim引申以及Linux下彩色进度条实现
    各大排序八方齐聚!
    Docker三剑客:Compose、Machine和Swarm
  • 原文地址:https://www.cnblogs.com/gxldan/p/4066904.html
Copyright © 2020-2023  润新知