85 lines
3.2 KiB
PHP
85 lines
3.2 KiB
PHP
<?php
|
||
// 保存图片到本地,不做清理;保存目录按照远程URL的路径结构组织
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
|
||
function respond($ok, $message = '', $path = '') {
|
||
echo json_encode(['success' => $ok, 'message' => $message, 'path' => $path], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||
exit;
|
||
}
|
||
|
||
// 读取JSON输入
|
||
$raw = file_get_contents('php://input');
|
||
$data = json_decode($raw, true);
|
||
$url = $data['url'] ?? '';
|
||
if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
|
||
respond(false, 'URL无效');
|
||
}
|
||
|
||
// 只允许 http/https
|
||
$scheme = parse_url($url, PHP_URL_SCHEME);
|
||
if (!in_array(strtolower($scheme), ['http','https'])) {
|
||
respond(false, '仅支持http/https图片地址');
|
||
}
|
||
|
||
$root = __DIR__ . '/../pictures';
|
||
if (!is_dir($root)) { @mkdir($root, 0777, true); }
|
||
|
||
// 解析远程路径:按照域名后的路径作为保存文件夹结构
|
||
$path = parse_url($url, PHP_URL_PATH) ?: '';
|
||
if (!$path) { respond(false, '无法解析远程路径'); }
|
||
|
||
// 将路径拆分并进行安全过滤,避免非法字符与上级目录
|
||
$segments = array_values(array_filter(explode('/', $path), function($s){ return $s !== ''; }));
|
||
if (!count($segments)) { respond(false, '路径为空'); }
|
||
|
||
$filename = array_pop($segments);
|
||
$safeSegs = array_map(function($seg){
|
||
$seg = preg_replace('/[^A-Za-z0-9._-]+/u', '_', $seg);
|
||
return trim($seg, '._-') ?: 'unk';
|
||
}, $segments);
|
||
$safeName = preg_replace('/[^A-Za-z0-9._-]+/u', '_', $filename);
|
||
if (!$safeName) { $safeName = 'image_' . time() . '.jpg'; }
|
||
|
||
$targetDir = $root;
|
||
foreach ($safeSegs as $seg) { $targetDir .= DIRECTORY_SEPARATOR . $seg; if (!is_dir($targetDir)) { @mkdir($targetDir, 0777, true); } }
|
||
$targetPath = $targetDir . DIRECTORY_SEPARATOR . $safeName;
|
||
|
||
// 如果文件已存在则跳过下载
|
||
if (file_exists($targetPath)) {
|
||
respond(true, '文件已存在,跳过下载', str_replace($_SERVER['DOCUMENT_ROOT'], '', $targetPath));
|
||
}
|
||
|
||
// 下载保存
|
||
try {
|
||
$read = @fopen($url, 'rb');
|
||
if (!$read) { respond(false, '无法读取远程图片'); }
|
||
$write = @fopen($targetPath, 'wb');
|
||
if (!$write) { respond(false, '无法写入文件'); }
|
||
stream_copy_to_stream($read, $write);
|
||
fclose($read);
|
||
fclose($write);
|
||
} catch (Throwable $e) {
|
||
respond(false, '保存失败: ' . $e->getMessage());
|
||
}
|
||
|
||
$bytes = @filesize($targetPath) ?: 0;
|
||
try {
|
||
$statsRoot = __DIR__ . '/../stats';
|
||
if (!is_dir($statsRoot)) { @mkdir($statsRoot, 0777, true); }
|
||
$dailyPath = $statsRoot . '/daily.json';
|
||
$today = (new DateTime('now'))->format('Y-m-d');
|
||
$daily = [];
|
||
if (file_exists($dailyPath)) {
|
||
$rawDaily = @file_get_contents($dailyPath);
|
||
$decoded = json_decode($rawDaily, true);
|
||
if (is_array($decoded)) { $daily = $decoded; }
|
||
}
|
||
if (!isset($daily[$today]) || !is_array($daily[$today])) {
|
||
$daily[$today] = ['visits' => 0, 'video_plays' => 0, 'picture_shows' => 0, 'uv' => 0, 'bandwidth_in' => 0, 'bandwidth_out' => 0];
|
||
}
|
||
$daily[$today]['bandwidth_out'] += (int)$bytes;
|
||
@file_put_contents($dailyPath, json_encode($daily, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||
} catch (Throwable $e) {}
|
||
|
||
respond(true, '保存成功', str_replace($_SERVER['DOCUMENT_ROOT'], '', $targetPath));
|