File size: 11.24Kb
<?php
require_once __DIR__ . '/../config/bootstrap.php';
require_once __DIR__ . '/../config/auth.php';
require_once __DIR__ . '/../config/functions.php';
if (!is_logged_in()) {
header('Location: ' . BASE_URL . 'login.php');
exit;
}
$errors = [];
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$csrf_token = $_POST['csrf'] ?? $_POST['csrf_token'] ?? '';
if (empty($csrf_token)) {
$errors[] = 'Отсутствует CSRF токен';
error_log('CSRF token missing in POST data: ' . print_r($_POST, true));
} elseif (!check_csrf($csrf_token)) {
$errors[] = 'Ошибка безопасности. Попробуйте снова.';
error_log('CSRF check failed. Token from POST: ' . $csrf_token . ', Token in session: ' . ($_SESSION['csrf_token'] ?? 'none'));
} elseif (!isset($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
$errors[] = 'Ошибка загрузки файла. Код ошибки: ' . ($_FILES['photo']['error'] ?? 'No file');
error_log('File upload error: ' . ($_FILES['photo']['error'] ?? 'No file uploaded'));
} else {
$allowed_types = ['image/jpeg', 'image/png', 'image/jpg'];
$tmp_name = $_FILES['photo']['tmp_name'];
if (!file_exists($tmp_name)) {
$errors[] = 'Временный файл не существует.';
error_log('Temporary file does not exist: ' . $tmp_name);
} else {
if ($_FILES['photo']['size'] > 10 * 1024 * 1024) {
$errors[] = 'Файл слишком большой. Максимальный размер: 10 МБ.';
} else {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$file_type = finfo_file($finfo, $tmp_name);
finfo_close($finfo);
error_log('Detected file type: ' . $file_type);
if ($file_type === 'image/jpg') {
$file_type = 'image/jpeg';
}
if (!in_array($file_type, $allowed_types)) {
$errors[] = 'Разрешены только JPG и PNG файлы. Загружен тип: ' . $file_type;
} else {
$original_name = $_FILES['photo']['name'];
$extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
if ($extension === 'jpg') {
$extension = 'jpeg';
}
$filename = bin2hex(random_bytes(8)) . '.' . $extension;
$upload_dir = __DIR__ . '/../uploads/photos/';
if (!is_dir($upload_dir)) {
if (!mkdir($upload_dir, 0755, true)) {
$errors[] = 'Не удалось создать директорию для загрузки.';
error_log('Failed to create upload directory: ' . $upload_dir);
}
}
if (empty($errors)) {
$destination = $upload_dir . $filename;
if (move_uploaded_file($tmp_name, $destination)) {
error_log('File moved successfully to: ' . $destination);
try {
$stmt = $pdo->prepare("INSERT INTO photos (user_id, filename, uploaded_at, status) VALUES (:user_id, :filename, NOW(), 'Новый')");
$stmt->execute([
'user_id' => $_SESSION['user_id'],
'filename' => $filename
]);
$success = true;
$last_id = $pdo->lastInsertId();
error_log('Photo saved to database with ID: ' . $last_id);
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
} catch (PDOException $e) {
$errors[] = 'Ошибка базы данных: ' . $e->getMessage();
error_log('Database error: ' . $e->getMessage());
if (file_exists($destination)) {
unlink($destination);
}
}
} else {
$errors[] = 'Не удалось сохранить файл.';
error_log('Failed to move uploaded file. Error: ' . error_get_last()['message'] ?? 'unknown');
}
}
}
}
}
}
}
include __DIR__ . '/../includes/header.php';
?>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-5">
<div class="card shadow-sm border-0 animate__animated animate__fadeInDown">
<div class="card-body p-4">
<h3 class="card-title mb-4 text-center fw-bold">
<i class="bi bi-cloud-upload-fill"></i> Загрузка фотографии
</h3>
<?php if ($success): ?>
<div class="alert alert-success mb-3">
<div class="d-flex align-items-center">
<i class="bi bi-check-circle-fill fs-4 me-3"></i>
<div>
<h5 class="alert-heading mb-1">Успешно!</h5>
<p class="mb-0">Фотография успешно загружена и отправлена на печать.</p>
</div>
</div>
</div>
<?php endif; ?>
<?php if ($errors): ?>
<div class="alert alert-danger mb-3">
<div class="d-flex align-items-center">
<i class="bi bi-exclamation-circle-fill fs-4 me-3"></i>
<div>
<h5 class="alert-heading mb-1">Ошибка загрузки</h5>
<?php foreach ($errors as $error): ?>
<p class="mb-1">• <?= e($error) ?></p>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data" class="needs-validation" novalidate>
<?= csrf_input(); ?>
<div class="mb-4">
<label for="photo" class="form-label fw-bold">
<i class="bi bi-image"></i> Выберите фотографию
</label>
<input type="file"
class="form-control"
id="photo"
name="photo"
accept=".jpg,.jpeg,.png"
required>
<div class="form-text">
<i class="bi bi-info-circle"></i> Поддерживаемые форматы: JPG, PNG. Максимальный размер: 10 МБ.
</div>
<div class="invalid-feedback">
Пожалуйста, выберите файл изображения.
</div>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary btn-lg">
<i class="bi bi-cloud-upload"></i> Загрузить фотографию
</button>
<a href="<?= BASE_URL ?>" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> На главную
</a>
</div>
</form>
</div>
<div class="card-footer bg-white border-0 text-center">
<small class="text-muted">
<i class="bi bi-shield-check"></i> Ваши фотографии защищены и не передаются третьим лицам
</small>
</div>
</div>
<div class="alert alert-info mt-4">
<div class="d-flex align-items-center">
<i class="bi bi-lightbulb fs-4 me-3"></i>
<div>
<h6 class="alert-heading mb-1">Советы по загрузке</h6>
<ul class="mb-0 ps-3">
<li>Используйте фотографии в хорошем качестве</li>
<li>Оптимальное разрешение: от 300 DPI</li>
<li>Рекомендуемый формат: JPG</li>
<li>Фотографии автоматически проверяются на качество</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('form');
const fileInput = document.getElementById('photo');
fileInput.addEventListener('change', function() {
const file = this.files[0];
const maxSize = 10 * 1024 * 1024; // 10 МБ
if (file && file.size > maxSize) {
alert('Файл слишком большой. Максимальный размер: 10 МБ.');
this.value = '';
}
if (file) {
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if (!allowedTypes.includes(file.type)) {
alert('Разрешены только JPG и PNG файлы.');
this.value = '';
}
}
});
(function() {
'use strict';
const forms = document.querySelectorAll('.needs-validation');
Array.from(forms).forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
})();
});
</script>
<?php
include __DIR__ . '/../includes/footer.php';
?>