Files
MoYuBan/api/upload_picture.php

112 lines
4.2 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
// 接收用户投稿的图片,保存到待审核目录 pictures_pending
// 不直接进入 pictures/images/,待管理员在 review_pictures.php 审核后再转存并自动重命名
header('Content-Type: text/html; charset=utf-8');
$pendingDir = __DIR__ . '/../pictures_pending';
if (!is_dir($pendingDir)) {
@mkdir($pendingDir, 0777, true);
}
function sanitizeFileName($name) {
$name = preg_replace('/[^A-Za-z0-9_\-\.\(\)\[\]\s]/u', '_', $name);
if (strlen($name) > 120) {
$ext = pathinfo($name, PATHINFO_EXTENSION);
$base = pathinfo($name, PATHINFO_FILENAME);
$base = substr($base, 0, 100);
$name = $base . ($ext ? ('.' . $ext) : '');
}
return $name;
}
function html($s) { return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
$allowed = ['jpg','jpeg','png','gif','webp'];
$maxSize = 10 * 1024 * 1024; // 10MB
$title = isset($_POST['title']) ? trim($_POST['title']) : '';
if (!isset($_FILES['picture'])) {
echo '<p>未接收到文件。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
// 上传错误处理
if (!empty($_FILES['picture']['error'])) {
$err = (int)$_FILES['picture']['error'];
if ($err === UPLOAD_ERR_INI_SIZE || $err === UPLOAD_ERR_FORM_SIZE) {
echo '<p>上传失败:文件大小超过服务器限制。请确保图片不超过 10MB。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
echo '<p>上传失败,错误码:' . $err . '。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
if (!is_uploaded_file($_FILES['picture']['tmp_name'])) {
echo '<p>文件上传失败。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
$file = $_FILES['picture'];
$origName = $file['name'] ?? 'uploaded_image';
$safeName = sanitizeFileName($origName);
$ext = strtolower(pathinfo($safeName, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
echo '<p>仅支持文件类型jpg / jpeg / png / gif / webp。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
// 大小限制 10MB
$size = (int)($_FILES['picture']['size'] ?? 0);
if ($size > $maxSize) {
echo '<p>图片大小超过 10MB 限制,投稿失败。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
$unique = date('Ymd_His') . '_' . mt_rand(1000,9999) . '.' . $ext;
$target = $pendingDir . '/' . $unique;
if (!move_uploaded_file($file['tmp_name'], $target)) {
echo '<p>保存文件失败,请稍后重试。</p><p><a href="../upload_picture.php">返回图片投稿页</a></p>';
exit;
}
$bytes = (int)($file['size'] ?? 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_in'] += (int)$bytes;
@file_put_contents($dailyPath, json_encode($daily, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
} catch (Throwable $e) {}
$meta = [
'original_name' => $origName,
'saved_name' => basename($target),
'title' => $title,
'uploaded_at' => date('c'),
'size' => $file['size'] ?? 0,
'type' => $file['type'] ?? '',
];
@file_put_contents($pendingDir . '/' . basename($target) . '.json', json_encode($meta, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
echo '<div style="padding:16px;border:1px solid #e33;border-radius:8px;max-width:640px;margin:24px auto;">';
echo '<p>投稿成功!图片已进入待审核队列。</p>';
if (!empty($title)) {
echo '<p>标题:' . html($title) . '</p>';
}
echo '<p>管理员可前往 <a href="../review_pictures.php">图片审核页面</a> 进行审批。</p>';
echo '<p><a href="../upload_picture.php">继续投稿</a> 或 <a href="../index.php">返回首页</a></p>';
echo '</div>';
?>