php代码不执行不产生任何异常
微wx笑
2019-09-04【帝国CMS】
21
0关键字:
帝国cms php
最近遇到一个比较奇怪的问题,下面这段拉取远程图片的代码,readfile部分不执行,也不抛出任何异常。php.ini中display_errors=On,error_reporting=
E_ALL也配置了,甚至代码中使用
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'on');
都没有用,这到底是什么原因呢?
php代码不执行不产生任何异常
最近遇到一个比较奇怪的问题,下面这段拉取远程图片的代码,readfile部分不执行,也不抛出任何异常。php.ini中display_errors=On,error_reporting= E_ALL也配置了,甚至代码中使用
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'on');
都没有用,这到底是什么原因呢?
/**
* 拉取远程图片
* @return mixed
*/
private function saveRemote()
{
$imgUrl = htmlspecialchars($this->fileField);
$imgUrl = str_replace("&", "&", $imgUrl);
//http开头验证
if (strpos($imgUrl, "http") !== 0) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
return;
}
preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);
$host_with_protocol = count($matches) > 1 ? $matches[1] : '';
// 判断是否是合法 url
if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
$this->stateInfo = $this->getStateInfo("INVALID_URL");
return;
}
preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
$host_without_protocol = count($matches) > 1 ? $matches[1] : '';
// 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
$ip = gethostbyname($host_without_protocol);
// 判断是否是私有 ip
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
$this->stateInfo = $this->getStateInfo("INVALID_IP");
return;
}
//获取请求头并检测死链
$heads = get_headers($imgUrl, 1);
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
$this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
return;
}
//格式验证(扩展名验证和Content-Type验证)
$fileType = strtolower(strrchr($imgUrl, '.'));
if (strpos($fileType, "?")){
$fileType = strstr($fileType, "?", true);
}
if (!isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
return;
}else{
if (count($this->config['allowFiles']) > 0){
if (!in_array($fileType, $this->config['allowFiles'])){
//$this->stateInfo = $this->getStateInfo("ERROR_HTTP_ALLOWFILES").$heads['Content-Type']; //image/webp
return;
}
}
}
//打开输出缓冲区并获取远程图片
ob_start();
$context = stream_context_create(
array('http' => array(
'follow_location' => false // don't follow redirects
))
);
readfile($imgUrl, false, $context);
$img = ob_get_contents();
ob_end_clean();
$imgUrl2 = $imgUrl;
if (strpos($imgUrl, "?")){
$imgUrl2 = substr($imgUrl, 0, strripos($imgUrl, "?"));
}
preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl2, $m);
$this->oriName = $m ? $m[1]:"";
$this->fileSize = strlen($img);
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->filePath = $this->getFilePath();
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//创建目录失败
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移动文件
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->stateInfo = $this->stateMap[0];
}
}没有执行的代码段:
//打开输出缓冲区并获取远程图片
ob_start();
$context = stream_context_create(
array('http' => array(
'follow_location' => false // don't follow redirects
))
);
readfile($imgUrl, false, $context);
$img = ob_get_contents();
ob_end_clean();关键并不是所有情况都不执行,而是拉取微信公众号的图片时存在这一问题。
而改用以下代码是可以拉取成功的:
function mkdirs($dir, $mode = 0777)
{
if (is_dir($dir) || @mkdir($dir, $mode)) return TRUE;
if (!mkdirs(dirname($dir), $mode)) return FALSE;
return @mkdir($dir, $mode);
}
function download123($url, $path = 'images/')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
$file = curl_exec($ch);
curl_close($ch);
$filename = pathinfo($url, PATHINFO_BASENAME);
if (stripos($filename, "?")){
$filename = strstr($filename, "?", true);
}
if (!stripos($filename, ".")){
$filename = $filename.".jpeg";
}
mkdirs($filename);
$resource = fopen($path . $filename, 'a');
echo "<br>4";
fwrite($resource, $file);
fclose($resource);
echo "<br>5<br>";
}注:mkdirs 函数有问题,没有对传入路径的文件名进行处理。
本文由 微wx笑 创作,采用 署名-非商业性使用-相同方式共享 4.0 许可协议,转载请附上原文出处链接及本声明。
原文链接:https://www.ivu4e.cn/blog/EmpireCMS/2019-09-04/176.html



