然后呢,凭借着“能白嫖就白嫖”的精神,我将收集来的博客图片挨个上传到了图床,收获了100个链接
但是,如何随机调用图片呢?
简单的3个办法
- 放在一个文本文件里,通过file()解析
- sqlite3 SELECT
- mysql SELECT + RANDOM
但是我就是不喜欢,花了2小时,终于完成了强大的zSet
zSet相当于一个文件等宽数组,文件是这样的:
而且API非常简洁,就那么几个:
那么,我就简单地小时牛刀,创建了两个PHP文件,使用file()函数或使用zSet
<?php
// 文件1:使用zSet
include_once 'create.php';
$set = new SetFile('db.zset',true);
$total = $set->total;
header('Location:'.$set->get(rand(0,$total)));
// 文件2:简洁的file大法
$data = file('img.list');
header('Location:'+$data[rand(0,count($data))]);
结果
izS # curl localhost/blog/way2.php -v
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /blog/way2.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 302 Found
< Server: nginx
< Date: Sat, 02 Sep 2023 06:47:19 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/8.2.7
< Location: https://picss.sunbangyan.cn/2023/09/02/j37c5j.jpg
< Access-Control-Allow-Origin: *
< X-TimeUsed: 0.001
<
* Connection #0 to host localhost left intact
izS # curl localhost/blog/random.php -v
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /blog/random.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 302 Found
< Server: nginx
< Date: Sat, 02 Sep 2023 06:47:46 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/8.2.7
< Location: https://picdm.sunbangyan.cn/2023/09/02/j3xlss.jpg
< Access-Control-Allow-Origin: *
< X-TimeUsed: 0.001
<
* Connection #0 to host localhost left intact
不明显,那么我们扩充容量继续
<?php
include_once 'create.php';
$set = new SetFile('db.zset',false);
$file = fopen('img.list','w');
for ($i = 0; $i < 20000; $i++) {
$val = md5(rand($i,$i+10000000));
$set->push($val);
fwrite($file,$val);
}
$set->save();
2万条数据并发,我们看看结果:
izS # curl localhost/blog/random.php -v
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /blog/random.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 302 Found
< Server: nginx
< Date: Sat, 02 Sep 2023 06:57:49 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/8.2.7
< Location: b431a69da5657ad54c2dda310abdf2d4
< Access-Control-Allow-Origin: *
< X-TimeUsed: 0.001
<
* Connection #0 to host localhost left intact
izS # curl localhost/blog/way2.php -v
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /blog/way2.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 302 Found
< Server: nginx
< Date: Sat, 02 Sep 2023 06:57:42 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/8.2.7
< Location: c861927528520dc2a3fafabfccbe8338
< Access-Control-Allow-Origin: *
< X-TimeUsed: 0.003
<
* Connection #0 to host localhost left intact
非常明显,如果数据量很大,zSet非常有优势!始终是1ms的高速
- file()是整个文件解析,因此文件越大越慢
- zSet是等宽数据库,根据ID找到位置读取,因此始终1ms高速
于是乎,zSet源码在此,需要的自取!
<?php
class SetFile{
private $file,$temp,$path,$length=0;
protected $append = [],$isnf = false,
$size = 0;
public $total = 0;
const HEAD = 'ZSET ',
SEPARATE = "\033",
NUMLEN = 5;
function __construct(string $file,bool $readonly=false){
if(!file_exists($file) and !touch($file)) throw new Exception('IO Error.');
$this->path = $file;
$this->file = fopen($file,'r');
$this->length = filesize($file);
if(!$readonly) $this->temp = fopen($file.'.lock','w');
if(filesize($file) > (strlen(self::HEAD) + self::NUMLEN))
$this->_init();
else $this->isnf = true;
}
private function _init(){
fseek($this->file,0);
if(self::HEAD != fread($this->file,strlen(self::HEAD)))
throw new Exception('Not a vaild setFile');
fseek($this->file,strlen(self::HEAD));
$this->size = (int)fread($this->file,self::NUMLEN); // 单列大小
if($this->size <= 0) throw new Exception('illegal meta.Wrong zset file!');
$this->total = (filesize($this->path) - strlen(self::HEAD) - self::NUMLEN) / $this->size; // 总数
}
function push(string $data){
if($this->size <= strlen($data))
$this->size = strlen($data) + 1;
$this->append[] = $data;
return $this;
}
function get(int $num){
if($this->size <= 0 || $this->isnf) return null;
$position = strlen(self::HEAD) + self::NUMLEN + $num * $this->size;
if($position >= $this->length) return null;
fseek($this->file,$position);
return $this->_filter(fread($this->file,$this->size));
}
private function _filter(string $data){
$end = strpos($data,self::SEPARATE,1);
if($end === false) throw new Exception('illegal data found.bad set.');
return substr($data,0,$end);
}
function getAll(){
if($this->size <= 0 || $this->isnf) return [];
$tmp = [];
fseek($this->file,strlen(self::HEAD) + self::NUMLEN);
while(!feof($this->file))
$tmp[] = $this->_filter(fread($this->file,$this->size));
return $tmp;
}
function save(){
if(!$this->temp) throw new Exception('This file is Readonly.');
fseek($this->temp,0);
fwrite($this->temp,self::HEAD . str_pad($this->size,self::NUMLEN,'0',STR_PAD_LEFT));
$dataset = array_merge($this->getAll(),$this->append);
foreach ($dataset as $data){
if($this->size <= strlen($data))
throw new Exception('Broken file.illegal average length.');
// 缺位补齐
fwrite($this->temp,str_pad($data,$this->size,self::SEPARATE,STR_PAD_RIGHT));
// 完成
fdatasync($this->temp);
}
}
function __destruct(){
if($this->temp)
rename($this->path . '.lock',$this->path) and fclose($this->temp);
fclose($this->file);
}
}
本文由 zlh 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。