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 .= "\n";
      }
    }
    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;
 
posted @ 2013-06-27 22:53  gxldan  阅读(999)  评论(0编辑  收藏  举报