1、在实现渠道发布的过程中,存在待上传至渠道的文件过大的情况,进而导致上传失败。比如说抖音,暂时限制为 128 MB。如图1
2、但是现阶段的实现逻辑是,先基于文件的 HTTP (absolute_url:来源的资源文件的绝对URL) 下载文件后,得到文件的 relative_path:渠道发布的资源文件的相对路径,然后才能够获取到文件的大小。而这个实现阶段是异步的。如图2
3、现在希望优化用户的体验,能够在调用接口时,基于 HTTP 协议检测文件的大小(即不下载文件的情况下,获取文件的大小)。
4、参考 文件系统函数 filesize — 取得文件大小:https://www.php.net/manual/zh/function.filesize.php 。The simplest and most efficient implemention for getting remote filesize。获取远程文件大小的最简单和最有效的实现。如图3
5、执行 fopen() 时可以使用变量 $http_response_header。 其中包含响应标头的数组。打印变量 $http_response_header。如图4
<?php
function remote_filesize($url) {
static $regex = '/^Content-Length: *+/K/d++$/im';
// 将 $url 指定的名字资源绑定到一个流上,只读方式打开,将文件指针指向文件头
if (!$fp = @fopen($url, 'rb')) {
return false;
}
// 执行 fopen() 时可以使用变量 $http_response_header。 其中包含响应标头的数组。
if (
isset($http_response_header) &&
preg_match($regex, implode("/n", $http_response_header), $matches)
) {
print_r($http_response_header);
return (int)$matches[0];
}
echo 1;
return strlen(stream_get_contents($fp));
}
$startTime = time();
$url = 'https://www.shuijingwanwq.com/wp-content/uploads/2021/07/秦时明月第一集荧惑守心.mp4';
echo remote_filesize($url) . "/n";
$endTime = time();
echo '耗费时间:' . ($endTime - $startTime) . '秒';
?>
Array
(
[0] => HTTP/1.1 200 OK
[1] => Server: nginx
[2] => Date: Mon, 09 Aug 2021 05:46:41 GMT
[3] => Content-Type: video/mp4
[4] => Content-Length: 143162935
[5] => Last-Modified: Tue, 30 Oct 2018 09:52:18 GMT
[6] => Connection: close
[7] => ETag: "5bd829d2-8887e37"
[8] => Expires: Wed, 08 Sep 2021 05:46:41 GMT
[9] => Cache-Control: max-age=2592000
[10] => Strict-Transport-Security: max-age=15768000
[11] => Accept-Ranges: bytes
)
143162935
耗费时间:0秒
6、如果变量 $http_response_header 不存在,则 使用函数 stream_get_contents — 读取资源流到一个字符串。文件大小:1.27 MB,测试一下耗费时间:2秒,发现无法接受。决定当变量 $http_response_header 不存在时,返回 false。如图5
<?php
function remote_filesize($url) {
static $regex = '/^Content-Length: *+/K/d++$/im';
// 将 $url 指定的名字资源绑定到一个流上,只读方式打开,将文件指针指向文件头
if (!$fp = @fopen($url, 'rb')) {
return false;
}
// 执行 fopen() 时可以使用变量 $http_response_header。 其中包含响应标头的数组。
/*
if (
isset($http_response_header) &&
preg_match($regex, implode("/n", $http_response_header), $matches)
) {
print_r($http_response_header);
return (int)$matches[0];
}
*/
echo 1;
return strlen(stream_get_contents($fp));
}
$startTime = time();
$url = 'https://www.shuijingwanwq.com/wp-content/uploads/2021/07/兔子、牛、还有一只什么哟?认不出来了.mp4';
echo remote_filesize($url) . "/n";
$endTime = time();
echo '耗费时间:' . ($endTime - $startTime) . '秒';
?>
1334721 耗费时间:2秒
7、最终代码实现如下。如图6
<?php
function remote_filesize($url) {
static $regex = '/^Content-Length: *+/K/d++$/im';
// 将 $url 指定的名字资源绑定到一个流上,只读方式打开,将文件指针指向文件头
if (!$fp = @fopen($url, 'rb')) {
return 0;
}
// 执行 fopen() 时可以使用变量 $http_response_header。其中包含响应标头的数组。
if (
isset($http_response_header) &&
preg_match($regex, implode("/n", $http_response_header), $matches)
) {
print_r($http_response_header);
return (int)$matches[0];
}
return 0;
}
$startTime = time();
$url = 'https://www.shuijingwanwq.com/wp-content/uploads/2021/07/ChinaJoy 2015 上海 梦幻西游.mp4';
echo remote_filesize($url) . "/n";
$endTime = time();
echo '耗费时间:' . ($endTime - $startTime) . '秒';
?>
8、在调用接口时,基于 HTTP 协议检测文件的大小(即不下载文件的情况下,获取文件的大小),最终实现预期目标。如图7
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/250606.html
