Files
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/
- 12 code-workspace-Files
- STATUS-*.md
- viele M/D/R-Änderungen an bereits getrackten Files
- .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-08 02:27:02 +02:00

76 lines
2.2 KiB
PHP

<?php
/**
* POST /api/artifact
* Multipart-Upload für Modul-erzeugte Artefakte (Bilder, Karten, Audio).
*/
declare(strict_types=1);
require_once __DIR__ . '/../../bootstrap.php';
v2_validate_method('POST');
$auth = v2_auth_require('student');
$studentId = (int) ($auth['sub'] ?? 0);
$slug = $_POST['moduleSlug'] ?? '';
$label = $_POST['label'] ?? '';
if (!$slug) {
v2_response_error(400, 'missing_slug', 'Feld "moduleSlug" fehlt.');
}
if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
v2_response_error(400, 'upload_failed', 'Datei-Upload fehlgeschlagen.');
}
$file = $_FILES['file'];
$mimeType = mime_content_type($file['tmp_name']) ?: 'application/octet-stream';
// Erlaubte MIME-Typen
$allowedMime = ['image/png', 'image/jpeg', 'image/webp', 'audio/mpeg', 'audio/wav', 'audio/ogg', 'application/pdf'];
if (!in_array($mimeType, $allowedMime, true)) {
v2_response_error(415, 'unsupported_media_type', "MIME-Typ '$mimeType' nicht erlaubt.");
}
// Max 10 MB
if ($file['size'] > 10 * 1024 * 1024) {
v2_response_error(413, 'file_too_large', 'Max 10 MB pro Upload.');
}
// Ablage
$uploadDir = V2_ROOT . "/uploads/$slug/student-$studentId";
if (!is_dir($uploadDir)) {
if (!mkdir($uploadDir, 0775, true)) {
v2_response_error(500, 'upload_dir_failed', 'Upload-Ordner konnte nicht erstellt werden.');
}
}
$ext = pathinfo($file['name'], PATHINFO_EXTENSION) ?: 'bin';
$ext = preg_replace('/[^a-zA-Z0-9]/', '', $ext);
$filename = sprintf('%s-%s.%s', date('Ymd-His'), bin2hex(random_bytes(4)), $ext);
$destPath = "$uploadDir/$filename";
$publicUrl = V2_BASE_URL . "/uploads/$slug/student-$studentId/$filename";
if (!move_uploaded_file($file['tmp_name'], $destPath)) {
v2_response_error(500, 'move_failed', 'Datei konnte nicht abgelegt werden.');
}
v2_db_exec("
INSERT INTO artifacts_v2
(student_id, module_slug, mime_type, url, label, bytes)
VALUES
(:sid, :slug, :mt, :url, :lbl, :b)
", [
':sid' => $studentId,
':slug' => $slug,
':mt' => $mimeType,
':url' => $publicUrl,
':lbl' => $label,
':b' => (int) $file['size'],
]);
$id = (int) v2_db_insert_id();
v2_response_created([
'id' => $id,
'url' => $publicUrl,
'thumbnail' => null, // TODO: Thumbnail-Generation für Bilder
]);