Fix data export/import: PHP's default upload limits rejected real exports
Root cause: the export embeds the whole gallery as base64 directly in the JSON (that's how it stays a single self-contained file), which pushes a realistic export well past 40MB. PHP's post_max_size/upload_max_filesize default to values well under that on most hosting, so the browser's upload got silently discarded before the app ever saw it - PHP clears $_FILES and $_POST once post_max_size is exceeded, and the leftover raw body in php://input is unparsed multipart data, not JSON, so it fell into a generic "invalid file" 422 with no indication of what actually went wrong. Reproduced locally with a real ~43MB export against the previous 40M limit. Raises the limits to 200M via two paths, since we don't know which PHP SAPI the various hosting targets (All-Inkl, the Plesk test server) use: hifi/.htaccess sets php_value overrides for classic Apache module PHP, guarded by <IfModule> checks for several common module names so hosts running PHP-FPM/CGI (which ignore php_value and would otherwise choke on an unrecognized directive) skip the block instead of 500ing the entire site; hifi/api/public/.user.ini covers exactly that FPM/CGI case, which mod_php hosts in turn simply don't read. Also makes SettingsController::importData() detect an oversized upload by comparing Content-Length against the configured post_max_size, and report the actual limit instead of the generic corrupt-file message - so if some host's real limit is still too low, the admin sees why instead of a dead end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b1b66f1813
commit
a9aea99028
3 changed files with 79 additions and 1 deletions
|
|
@ -22,6 +22,34 @@ RewriteBase /
|
|||
# Upload mit "Methode nicht erlaubt" fehlschlägt.
|
||||
DirectorySlash Off
|
||||
|
||||
# Groessere Upload-/POST-Limits fuer den Daten-Export/-Import im Admin-Bereich
|
||||
# (der Export bettet die Bildergalerie als Base64 direkt in die JSON-Datei ein,
|
||||
# das kann schnell 40+ MB werden - PHPs Standard-Limits liegen oft niedriger).
|
||||
# Nur relevant, wenn PHP als Apache-Modul laeuft (mod_php) - die IfModule-Pruefung
|
||||
# sorgt dafuer, dass dieser Block auf FastCGI/PHP-FPM-Hosting (dort greift
|
||||
# stattdessen api/public/.user.ini) folgenlos uebersprungen wird, statt einen
|
||||
# "Invalid command"-Fehler fuer die ganze Seite auszuloesen.
|
||||
<IfModule mod_php.c>
|
||||
php_value upload_max_filesize 200M
|
||||
php_value post_max_size 200M
|
||||
php_value memory_limit 512M
|
||||
</IfModule>
|
||||
<IfModule php_module>
|
||||
php_value upload_max_filesize 200M
|
||||
php_value post_max_size 200M
|
||||
php_value memory_limit 512M
|
||||
</IfModule>
|
||||
<IfModule php7_module>
|
||||
php_value upload_max_filesize 200M
|
||||
php_value post_max_size 200M
|
||||
php_value memory_limit 512M
|
||||
</IfModule>
|
||||
<IfModule php8_module>
|
||||
php_value upload_max_filesize 200M
|
||||
php_value post_max_size 200M
|
||||
php_value memory_limit 512M
|
||||
</IfModule>
|
||||
|
||||
# API-Requests an den PHP-Front-Controller weiterleiten
|
||||
RewriteCond %{REQUEST_URI} ^/api/
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
|
|
|
|||
8
hifi/api/public/.user.ini
Normal file
8
hifi/api/public/.user.ini
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
; Groessere Upload-/POST-Limits fuer den Daten-Export/-Import im Admin-Bereich
|
||||
; (der Export bettet die Bildergalerie als Base64 direkt in die JSON-Datei ein,
|
||||
; das kann schnell 40+ MB werden). Greift auf PHP-FPM/CGI-Hosting (z.B. viele
|
||||
; Shared-Hosting-Umgebungen) - fuer klassisches Apache-Modul-PHP (mod_php)
|
||||
; uebernimmt stattdessen der php_value-Block in hifi/.htaccess.
|
||||
upload_max_filesize = 200M
|
||||
post_max_size = 200M
|
||||
memory_limit = 512M
|
||||
|
|
@ -70,11 +70,53 @@ class SettingsController
|
|||
exit;
|
||||
}
|
||||
|
||||
/** Wandelt eine php.ini-Groessenangabe ("200M", "1G", "512K") in Bytes um. */
|
||||
private static function iniBytes(string $value): int
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
return 0;
|
||||
}
|
||||
$num = (float) $value;
|
||||
return match (strtolower(substr($value, -1))) {
|
||||
'g' => (int) ($num * 1024 * 1024 * 1024),
|
||||
'm' => (int) ($num * 1024 * 1024),
|
||||
'k' => (int) ($num * 1024),
|
||||
default => (int) $value,
|
||||
};
|
||||
}
|
||||
|
||||
public static function importData(): void
|
||||
{
|
||||
if (!empty($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
|
||||
if (!empty($_FILES['file'])) {
|
||||
$uploadError = $_FILES['file']['error'];
|
||||
if ($uploadError === UPLOAD_ERR_INI_SIZE || $uploadError === UPLOAD_ERR_FORM_SIZE) {
|
||||
Http::error(
|
||||
'Die Datei überschreitet das Upload-Limit dieses Servers (aktuell ' . ini_get('upload_max_filesize') .
|
||||
'). Bitte den Hosting-Anbieter um ein höheres PHP-Upload-Limit bitten.',
|
||||
422
|
||||
);
|
||||
}
|
||||
if ($uploadError !== UPLOAD_ERR_OK) {
|
||||
Http::error('Datei-Upload fehlgeschlagen (Fehlercode ' . $uploadError . ').', 422);
|
||||
}
|
||||
$raw = file_get_contents($_FILES['file']['tmp_name']);
|
||||
} else {
|
||||
// Ein Upload, der post_max_size ueberschreitet, wird von PHP nicht in $_FILES
|
||||
// aufgenommen - der rohe Body ist ueber php://input aber trotzdem da (nur eben
|
||||
// noch als unverarbeitetes Multipart-Gemisch, kein gueltiges JSON). Deshalb direkt
|
||||
// Content-Length gegen das konfigurierte Limit pruefen, statt block auf einen
|
||||
// (nicht garantiert leeren) Body zu vertrauen - sonst landet eine zu grosse, aber
|
||||
// eigentlich intakte Export-Datei im irrefuehrenden generischen "ungueltige Datei"-Fehler.
|
||||
$contentLength = (int) ($_SERVER['CONTENT_LENGTH'] ?? 0);
|
||||
$maxPost = self::iniBytes((string) ini_get('post_max_size'));
|
||||
if ($maxPost > 0 && $contentLength > $maxPost) {
|
||||
Http::error(
|
||||
'Die Datei überschreitet das Größen-Limit dieses Servers (aktuell ' . ini_get('post_max_size') .
|
||||
'). Bitte den Hosting-Anbieter um ein höheres PHP-Upload-Limit (post_max_size) bitten.',
|
||||
422
|
||||
);
|
||||
}
|
||||
$raw = file_get_contents('php://input');
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue