Files
23cm/common/FileHelper.php
2026-01-25 18:18:09 +08:00

283 lines
9.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common;
use yii\helpers\BaseFileHelper;
use Yii;
/**
* Class FileHelper
* @package common\helpers
* @author jianyan74 <751393839@qq.com>
*/
class FileHelper extends BaseFileHelper
{
public $_speed = 0;
/**
* 检测目录并循环创建目录
*
* @param $catalogue
*/
public static function mkdirs($catalogue)
{
if (!file_exists($catalogue)) {
self::mkdirs(dirname($catalogue));
mkdir($catalogue, 0777);
exec('chown -R www.www '.$catalogue);
}
return true;
}
/**
* 写入日志
*
* @param $path
* @param $content
* @return bool|int
*/
public static function writeLog($path, $content)
{
$use_num = self::sysProbe();
// $use_num = Yii::$app->redis->get(CacheKeyEnum::SYSTEM_PROBE);
if ($use_num > 98) {
return false;
}
self::mkdirs(dirname($path));
return file_put_contents($path, date('Y-m-d H:i:s') . ">>>" . $content . "\r\n", FILE_APPEND);
}
/**
* 检测磁盘空间
* @return bool|int|string
*/
public static function sysProbe()
{
$total = round(@disk_total_space(".") / (1024 * 1024 * 1024), 2);
$free = round(@disk_free_space(".") / (1024 * 1024 * 1024), 2);
$use_num = intval($total - $free) ? : 1;
// exec("df -h", $systemInfo);
// $disk = $systemInfo[5] ?? $systemInfo[1]; //没有找到其他磁盘就默认第一个
// $use_num = 1;
// if ($disk) {
// $use_num = trim(substr($disk, -10, -7)) ? : 1; //媒介保后端服务器磁盘用量
// }
// Yii::$app->redis->setex(CacheKeyEnum::SYSTEM_PROBE, 3600, $use_num);
return $use_num;
}
/**
* 获取文件夹大小
*
* @param string $dir 根文件夹路径
* @return int
*/
public static function getDirSize($dir)
{
$handle = opendir($dir);
$sizeResult = 0;
while (false !== ($FolderOrFile = readdir($handle))) {
if ($FolderOrFile != "." && $FolderOrFile != "..") {
if (is_dir("$dir/$FolderOrFile")) {
$sizeResult += self::getDirSize("$dir/$FolderOrFile");
}
else {
$sizeResult += filesize("$dir/$FolderOrFile");
}
}
}
closedir($handle);
return $sizeResult;
}
/**
* 基于数组创建目录
*
* @param $files
*/
public static function createDirOrFiles($files)
{
foreach ($files as $key => $value) {
if (substr($value, -1) == '/') {
mkdir($value);
}
else {
file_put_contents($value, '');
}
}
}
/**
* 文件大小字节转换对应的单位
* @param $size
* @return string
*/
public static function convert($size)
{
$unit = array('b','kb','MB','GB','tb','pb');
return round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . '' . $unit[$i];
}
public static function downloadVideo($url)
{
// $is_url = Url::isUrl($url);
// if (!$is_url) {
// exit('不是正确的链接地址'); //exit掉下载下来打开会显示无法播放格式不支持文件已损坏等
// }
//获取文件信息
// $fileExt = pathinfo($url);
//获取文件的扩展名
// $allowDownExt = array ('mp4', 'mov');
//检测文件类型是否允许下载
// if (!in_array($fileExt['extension'], $allowDownExt)) {
// exit('不支持该格式');
// }
// 设置浏览器下载的文件名,这里还以原文件名一样
$filename = basename($url);
// 获取远程文件大小
// 注意filesize()无法获取远程文件大小
$headers = get_headers($url, 1);
$fileSize = $headers['Content-Length'];
if (ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
header_remove('Content-Encoding');
// 设置header头
// 因为不知道文件是什么类型的,告诉浏览器输出的是字节流
header('Content-Type: application/octet-stream');
// 告诉浏览器返回的文件大小类型是字节
header('Accept-Ranges:bytes');
// 告诉浏览器返回的文件大小
header('Content-Length: ' . $fileSize);
// 告诉浏览器文件作为附件处理并且设定最终下载完成的文件名称
header('Content-Disposition: attachment; filename="' . $filename . '"');
//针对大文件规定每次读取文件的字节数为4096字节直接输出数据
$read_buffer = 4096; //4096
$handle = fopen($url, 'rb');
//总的缓冲的字节数
$sum_buffer = 0;
//只要没到文件尾,就一直读取
while (!feof($handle) && $sum_buffer < $fileSize) {
echo fread($handle, $read_buffer);
$sum_buffer += $read_buffer;
}
fclose($handle);
exit;
}
/**
* @param String $file 要下载的文件路径
* @param String $name 文件名称,为空则与下载的文件名称一样
* @param boolean $reload 是否开启断点续传
* @return string
*/
public static function downloadFile($file, $name = '', $reload = false)
{
$log_path = Yii::getAlias('@runtime') . '/api/' . date('Ym') . '/' . date('d') . '/download.txt';
FileHelper::writeLog($log_path, $file);
$fp = fopen($file, 'rb');
if ($fp) {
if ($name == '') {
$name = basename($file);
}
$header_array = get_headers($file, true);
// 下载本地文件,获取文件大小
if (!$header_array) {
$file_size = filesize($file);
} else {
$file_size = $header_array['Content-Length'];
}
FileHelper::writeLog($log_path, json_encode($_SERVER, JSON_UNESCAPED_UNICODE));
if (isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
$ranges = self::getRange($file_size);
} else {
//第一次连接
$size2 = $file_size - 1;
header("Content-Range: bytes 0-$size2/$file_size"); //Content-Range: bytes 0-4988927/4988928
header("Content-Length: " . $file_size); //输出总长
}
$ua = $_SERVER["HTTP_USER_AGENT"];//判断是什么类型浏览器
header('cache-control:public');
header('content-type:application/octet-stream');
$encoded_filename = urlencode($name);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
//解决下载文件名乱码
if (preg_match("/MSIE/", $ua) || preg_match("/Trident/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename*="utf8\'\'' . $name . '"');
} else if (preg_match("/Chrome/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else {
header('Content-Disposition: attachment; filename="' . $name . '"');
}
//header('Content-Disposition: attachment; filename="' . $name . '"');
if ($reload && $ranges != null) { // 使用续传
header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges:bytes');
// 剩余长度
header(sprintf('content-length:%u', $ranges['end'] - $ranges['start']));
// range信息
header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
FileHelper::writeLog($log_path, sprintf('content-length:%u', $ranges['end'] - $ranges['start']));
// fp指针跳到断点位置
fseek($fp, sprintf('%u', $ranges['start']));
} else {
header('HTTP/1.1 200 OK');
header('content-length:' . $file_size);
}
while (!feof($fp)) {
echo fread($fp, 4096);
ob_flush();
}
($fp != null) && fclose($fp);
} else {
return '';
}
}
/** 设置下载速度
* @param int $speed
*/
public function setSpeed($speed)
{
if (is_numeric($speed) && $speed > 16 && $speed < 4096) {
$this->_speed = $speed;
}
}
/** 获取header range信息
* @param int $file_size 文件大小
* @return Array
*/
private static function getRange($file_size)
{
if (isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
$range = preg_replace('/[\s|,].*/', '', $range);
$range = explode('-', substr($range, 6));
if (count($range) < 2) {
$range[1] = $file_size;
}
$range = array_combine(array('start','end'), $range);
if (empty($range['start'])) {
$range['start'] = 0;
}
if (empty($range['end'])) {
$range['end'] = $file_size;
}
return $range;
}
return null;
}
}