Files
MoYuBan/api/upload_video.php

115 lines
4.1 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
// 接收用户投稿的视频,保存到待审核目录 videos_pending
// 不直接进入 videos/,待管理员在 review.php 审核后再转存并自动重命名
header('Content-Type: text/html; charset=utf-8');
$pendingDir = __DIR__ . '/../videos_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 = ['mp4','webm','mov'];
$maxSize = 50 * 1024 * 1024; // 50MB
$title = isset($_POST['title']) ? trim($_POST['title']) : '';
if (!isset($_FILES['video'])) {
echo '<p>未接收到文件。</p><p><a href="../upload.php">返回投稿页</a></p>';
exit;
}
// 上传错误处理
if (!empty($_FILES['video']['error'])) {
$err = (int)$_FILES['video']['error'];
if ($err === UPLOAD_ERR_INI_SIZE || $err === UPLOAD_ERR_FORM_SIZE) {
echo '<p>上传失败:文件大小超过服务器限制。请确保视频不超过 50MB。</p><p><a href="../upload.php">返回投稿页</a></p>';
exit;
}
echo '<p>上传失败,错误码:' . $err . '。</p><p><a href="../upload.php">返回投稿页</a></p>';
exit;
}
if (!is_uploaded_file($_FILES['video']['tmp_name'])) {
echo '<p>文件上传失败。</p><p><a href="../upload.php">返回投稿页</a></p>';
exit;
}
$file = $_FILES['video'];
$origName = $file['name'] ?? 'uploaded_video';
$safeName = sanitizeFileName($origName);
$ext = strtolower(pathinfo($safeName, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
echo '<p>仅支持文件类型mp4 / webm / mov。</p><p><a href="../upload.php">返回投稿页</a></p>';
exit;
}
// 大小限制 50MB
$size = (int)($_FILES['video']['size'] ?? 0);
if ($size > $maxSize) {
echo '<p>视频大小超过 50MB 限制,投稿失败。</p><p><a href="../upload.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.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.php">审核页面</a> 进行审批。</p>';
echo '<p><a href="../upload.php">继续投稿</a> 或 <a href="../index.php">返回首页</a></p>';
echo '</div>';
?>