Files
backend/app/Helpers/ArticleHelper.php
toom1996 9f8710f069 update
2025-07-29 12:43:17 +08:00

118 lines
4.8 KiB
PHP
Raw Permalink 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\Helpers;
use function Hyperf\Support\env;
class ArticleHelper
{
public static function saveImagesFromArticle(string $html, string $savePath = '', string $srcPrefix = '/uploads/')
{
if (!$savePath) {
$savePath = env('UPLOAD_ROOT', '');
if (!$savePath) {
throw new \Exception('找不到存储图片的路径信息。');
}
}
// 创建保存图片的目录,如果没有的话
if (!file_exists($savePath)) {
mkdir($savePath, 0777, true);
}
// 正则匹配所有 img 标签的 src 属性
preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $html, $matches);
// $matches[1] 包含所有 img 标签的图片 URL
$imageUrls = $matches[1];
// 遍历所有图片 URL 下载并保存
foreach ($imageUrls as $imageUrl) {
// 解析图片的文件名
$imageName = basename(parse_url($imageUrl, PHP_URL_PATH));
// 获取文件扩展名(如果没有扩展名,需要根据图片内容判断)
$extension = pathinfo($imageName, PATHINFO_EXTENSION);
if (empty($extension)) {
$imageContent = file_get_contents(trim($imageUrl, '\\'));
$finfo = finfo_open(FILEINFO_MIME_TYPE); // 获取 MIME 类型
$mimeType = finfo_buffer($finfo, $imageContent);
finfo_close($finfo);
// 根据 MIME 类型设置文件扩展名
if ($mimeType == 'image/jpeg') {
$extension = 'jpg';
} elseif ($mimeType == 'image/png') {
$extension = 'png';
} elseif ($mimeType == 'image/gif') {
$extension = 'gif';
} elseif ($mimeType == 'image/webp') { // 添加对 webp 的支持
$extension = 'webp';
} else {
continue; // 如果无法判断,跳过这张图片
}
// 用新的扩展名更新文件名
$imageName .= '.' . $extension;
}
// 本地保存路径
$localPath = $savePath . '/' . $imageName;
// 使用带 Cookie 的 cURL 下载图片
$result = self::downloadImageWithCookie($imageUrl, $localPath);
if ($result) {
// 更新 HTML 中 img 标签的 src 为本地路径
$html = str_replace($imageUrl, $srcPrefix . $imageName, $html);
}
}
return $html;
}
private static function downloadImageWithCookie($imageUrl, $savePath) {
// 2. 构造 HTTP 请求头 (Headers)
// 复制浏览器中的大部分 Header提高请求成功率
$headers = [
'accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
'accept-language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'cache-control: no-cache',
'cookie: ASP.NET_SessionId=tcth0to5f4rctrr2ejcxoley; User_Behavior_Cache=JXO3LM97XAP5BK1EKNAENZ76L2ZOT9DY; _gid=GA1.2.1692255419.1753689656; _ga=GA1.1.574649996.1753689655; _ga_L98EL3NEEE=GS2.1.s1753694736$o2$g1$t1753695112$j60$l0$h0',
'pragma: no-cache',
'referer: https://news.vobao.com/',
'sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"',
'sec-ch-ua-mobile: ?0',
'sec-ch-ua-platform: "Windows"',
'sec-fetch-dest: image',
'sec-fetch-mode: no-cors',
'sec-fetch-site: same-site',
'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0',
];
// 3. 初始化 cURL
$ch = curl_init();
// 4. 设置 cURL 选项
curl_setopt($ch, CURLOPT_URL, $imageUrl); // 设置请求URL
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 设置请求头
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将结果作为字符串返回,而不是直接输出
curl_setopt($ch, CURLOPT_HEADER, false); // 不返回响应头部分
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
curl_setopt($ch, CURLOPT_ENCODING, ''); // 处理所有受支持的编码如gzip
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用SSL证书验证 (在某些环境下需要)
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置超时时间为30秒
// 5. 执行 cURL 请求
$imageData = curl_exec($ch);
// 6. 检查是否有错误发生
if (curl_errno($ch)) {
echo 'cURL 请求错误: ' . curl_error($ch);
return false;
}
// 8. 关闭 cURL 句柄
curl_close($ch);
return file_put_contents($savePath, $imageData);
}
}