Jak zachytit chyby/upozornění spjaté s post_max_size
- Fera
- Člen | 22
Zdravím,
lámu si hlavu jak nějak elegantně vyřešit následující:
mám tlačítko pro multiupload a submit. Jde mi o to je validovat, tak aby
upload prošel, případně ohlásil uživatli, že všechny jeho vybrané
soubory překročili limity.
Pronásleduje mě tato hláška, u které příčinu znám =>
Possible problem: you are starting session while already having some data in
output buffer. This may not work if the outputted data grows. Try starting the
session earlier.
Stiskni CTRL+U, a nad začátkem html je následující =>
<b>Warning</b>: POST Content-Length of 11105501 bytes exceeds the
limit of 8388608 bytes in <b>Unknown</b> on line
<b>0</b><br />
prošel jsem několik vláken na tuto problematiku, většina se týkala
přenastavení php.ini nebo tvorbou htaccess, příklad zde:
https://stackoverflow.com/…-memory-size
zde je nástřel kódu u kterého jsem si říkal, že by mohl fungovat ALE:
<?php
protected function createComponentUploadForm(){
$target = $this->getParameter('target');
$form = new Form;
$form->addMultiUpload('files', NULL)
->addRule(Form::MAX_FILE_SIZE, 'Maximální velikost souboru je 4 MB.', 4 * 1024 * 1024)
->addRule(Form::FILLED , "Zde vyberte soubory")
->addRule(array($this,'validateSize'), "Zde vyberte soubory");
$form['files']->getControlPrototype()->setid('multiplejpginput');
$form->addHidden('target');
$form['target']->setValue($target);
$form->addSubmit('confirm', 'Nahrát');
$form->onSuccess[] = array($this, 'uploadFormSucceeded');
return $form;
}
public function validateSize(\Nette\Application\UI\Form $form, $values)
{
// vrati minimu z post_max_size a max_file_size
$maxSize = $this->getMaximumFileUploadSize();
$fileSize = 0;
foreach ($values['files'] as $file) {
$fileSize += $file->getSize();
}
if ($fileSize > $maxSize)
$form->addError('Tato kombinace není možná.');
}
public function uploadFormSucceeded(\Nette\Application\UI\Form $form, $values)
{
// nejake cachry machry nesouvisejici s otazkou...
if ($file->isOk()) {
$file->move($path.'/'.$fileName);
}
$this->redirect('Upload:', array('target' => $target));
}
?>
Buď je tu jen nějaká logická chyba, která mi uniká, nebo dojde k zaslání chyby ještě před samotným vyvoláním a vyhodnocením $form->onSuccess[]. V takovém případě jsem otevřený jakýmkoliv dobrým nápadům :)
- Unlink
- Člen | 298
No toto priamo nieje chyba nette. V php je parameter
post_max_size
(nastavuje sa cez php.ini) ktorý hovorí o tom,
aká je maximálna veľkosť požiadavku. Ono sa do toho rátajú všetky
súbory dokopy. Čiže ty síce máš že
Maximální velikost souboru je 4 MB.
ale keď tam nahráš
povezdme tri 3MB súbory, tak ti to prekročí ten defaultný limit (8M)
- Fera
- Člen | 22
Jasné, to mi hlaval bere, na to je tam ta funkce validateSize, ve které jsem chtěl sečíst velikosti všech souborů, a v případě, že to překročím, tak zastavit odesílání nebo ohlásit chybu. Jenže to vypadá, že se ta funkce nějak neprovede. Na druhou stranu, toto podle mě musí jít nějak ošetřit. I kdybych přenastavil v php.ini například na 2000mb, stejně bych se bál, že někdo z hecu zkusí odeslat soubor(y) větší…
- enumag
- Člen | 2118
Vlastně jde spíše u tuhle issue.
Zatím to řeším tak, že jsem vypnul direktivu display_startup_errors, ta chyba se dá odchytit později nějak takto:
$files = $this->getPresenter()->getRequest()->getFiles();
if (count($files) !== 1 || !isset($files['upload'])) {
// If post_max_size is exceeded both $_POST and $_FILES are empty.
if (empty($_POST) && empty($_FILES) && isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) {
// ... chyba detekována
}
// případ který by neměl nastat, zatím zde vyhazuji BadRequestException
}
Editoval enumag (4. 5. 2016 11:20)
- Fera
- Člen | 22
To vypadá dobře, teď to zksouším a ještě bych se teda zeptal, jak vypínáš ten „display_startup_errors“, zkoušel jsem různě házet ini_set(‚display_errors‘,‚off‘) – presenter, basepresenter i index.php a nějak to nepomáhá…
a ten úsek kódu, ten taky nevím kam, momentálně jej mam v uploadFormSucceeded, měl bych jej mít jinde?
možná zkouším jen špatné kombinace :)
- enumag
- Člen | 2118
Tohle se musí nastavit v php.ini nebo v .htaccess. Ty chyby se dají do outputbufferu ještě než tvůj kód vůbec začne takže ini_set proběhne pozdě. A pozor že display_errors je něco jiného než display_startup_errors.
V uploadFormSucceeded je to ok. Jen ten kód je z mého případu kdy jsem řešil upload mimo formuláře. Ve formulářích typicky nepolezeš přes request.
- Fera
- Člen | 22
Ok, tak bych asi ještě potřeboval popošťouchnout
1. Co se vlastně děje u tebe zde?
<?php
// tady asi natahnes z pozadavku soubory
$files = $this->getPresenter()->getRequest()->getFiles();
// tady testujes, jestli neni jeden? why?... a $files['upload'] je u tebe neco jako submit?
if (count($files) !== 1 || !isset($files['upload']))
?>
Zkoušel jsem to obdobně, ale tady mi to právě běhá na ten badRequest
<?php
public function uploadFormSucceeded(\Nette\Application\UI\Form $form, $values)
{
$files = $values['files'];
if (count($files) !== 1 || !isset($files['upload'])) {
// If post_max_size is exceeded both $_POST and $_FILES are empty.
if (empty($_POST) && empty($_FILES) && isset($_SERVER['CONTENT_LENGTH']) &&
$_SERVER['CONTENT_LENGTH'] > 0) {
echo "chyba";
}
throw new \Nette\Application\BadRequestException("");
}
//...
}
?>
2. formular se nemenil
<?php
protected function createComponentUploadForm(){
$target = $this->getParameter('target');
$form = new Form;
if ($this->lang == 'cs'){
$form->addMultiUpload('files', NULL)
->addRule(Form::MAX_FILE_SIZE, 'Maximální velikost souboru je 4 MB.', 4 * 1024 * 1024)
->addRule(Form::FILLED , "Zde vyberte soubory");
} else {
$form->addMultiUpload('files', NULL)
->addRule(Form::MAX_FILE_SIZE, 'Maximum file size is 4 MB.', 4 * 1024 * 1024 )
->addRule(Form::FILLED , "Select your files");
}
$form->addHidden('target');
$form['target']->setValue($target);
$form->addSubmit('confirm', 'Nahrát');
$form->onSuccess[] = array($this, 'uploadFormSucceeded');
return $form;
}
?>
3. co se týká toho .htaccess, dal jsem tam:
php_flag display_startup_errors off
mám projekt členěný
- app
-----AdminModul
---------presenters
---------template
-----FrontModul
---------presenters
--------------presnterA
--------------presenterB
--------------uploadPresenter
--------------TADY MAM TEN .HTACCESS
---------templates
- www
------slozky
------slozkaProUpload
Možná jsem si model namyslel, celý špatně, ale nevím kam ten .htaccess hodit, poněvadž mi to ty hlášky pořád nepotlačuje. Napadá mě, hodit ho přímo tam, kde je index.php, ale tím potlačím hlášky všude…trochu jsem si myslel, že by to mohlo jít jen pro ten určitý presenter, ale to hádám.
Editoval Fera (4. 5. 2016 21:25)
- ondrusu
- Člen | 118
Ahoj, chtěl bych se zeptat jak toto řešit nějak na straně nette.
Všiml jsem si že v Nette\Froms je metoda
public function validateMaxPostSize()
{
if (!$this->submittedBy || strcasecmp($this->getMethod(), 'POST') || empty($_SERVER['CONTENT_LENGTH'])) {
return;
}
$maxSize = ini_get('post_max_size');
$units = array('k' => 10, 'm' => 20, 'g' => 30);
if (isset($units[$ch = strtolower(substr($maxSize, -1))])) {
$maxSize <<= $units[$ch];
}
if ($maxSize > 0 && $maxSize < $_SERVER['CONTENT_LENGTH']) {
$this->addError(sprintf(Validator::$messages[self::MAX_FILE_SIZE], $maxSize));
}
}
a proměnná maxSize
nastavuje přesně to co já potřebuji
vědět.
Jelikož direktivu post_max_size můžou mít na každým serveru jinak
nastavenou tak se tím nechci zabívat abych to nastavoval všude ručně do
formuláře na přímo
$form->addUpload('file_1')
->addRule(Form::MAX_FILE_SIZE, 'Maximální velikost souboru je 64 kB.', 64 * 1024);
Můžu si napsat něco jako toto:
$max_post_kb = $this->getMaxPost('kb');
$max_post_b = $this->getMaxPost('b');
$form->addUpload('file_1')
->addRule(Form::MAX_FILE_SIZE, 'Maximální velikost souboru je ' . $max_post_kb, $max_post_b);
a metoda getMaxPost
by se zeptala ini_get
funkce a
nějak by si to „přepočítala“ na MB / Kb apod. abych tam měl čísla co
potřebuji.
Jen se ptám pokud je něco na straně nette ta abych něco nepsal
zbytčně.
díky za odpověď