Chyba poslání hlavičky když v output bufferu jsou již data
- igi
- Člen | 24
Zdravím, mám presenter, který má akci pro poslání vygenerovaného
souboru (soubor se generuje mým programem v C++, důvod je ten, že se může
volat ještě i odjinud mimo PHP), funguje to dobře, až na to, že mi Nette
zahlásí:
Possible problem: you are sending a HTTP header while already having some data
in output buffer. Try Tracy\OutputDebugger or send cookies/start session
earlier.
Menší problém je ten, že nevím jak ten debugger zapnout. Četl jsem
dokumentaci, ale nevím jak to napasovat přímo do té Nette konfigurace.
Větší problém je ten, že bych stejně nejspíše nevěděl co s tím
i tak :-D
Můj kód dané akce
public function actionSendAuthFile(): void
{
$id = $this->getUser()->id;
$fileName = system("/var/makeAuthFiles/bin/makeAuthFiles $id", $fileName);
$this->sendResponse(new FileResponse("/var/authFiles/$fileName", $fileName, 'text/plain'));
}
Tipuji, že problém by mohl být v předkovi presenteru, kde mám
public function startup(): void
{
parent::startup();
if (!$this->getUser()->isLoggedIn()) {
$this->redirect('Sign:in');
}
}
ale nevím co s tím, potřebuji soubor posílat jen danému přihlášenému uživateli, takže zrušit to přihlašování nemůžu.
Děkuji předem za rady jak to vyřešit.
- Marek Bartoš
- Nette Blogger | 1280
Zavolej \Tracy\OutputDebugger::enable()
kdekoli v
App\Bootstrap::boot()
- m.brecher
- Generous Backer | 873
@igi
Překvapil mě kód který Jsi použil:
$fileName = system("/var/makeAuthFiles/bin/makeAuthFiles $id", $fileName);
V dokumentaci PHP je tento příklad použití funkce system():
<?php
echo '<pre>';
// Outputs all the result of shellcommand "ls", and returns
// the last output line into $last_line. Stores the return value
// of the shell command in $retval.
$last_line = system('ls', $retval);
// Printing additional info
echo '
</pre>
<hr />Last line of the output: ' . $last_line . '
<hr />Return value: ' . $retval;
?>
Nemám teď čas, abych to otestoval, takže to píšu bez záruky, ale řekl bych, že system() rovnou pošle výsledek příkazu shellu na výstup – a zřejmě tam nebudou ty správné http hlavičky. Výstup si současně zachytíš do $retval, ale to není to samé jako výstup do $last_line !! Pak odesíláš pomocí Nette, ale já se domnívám, že system() už pravděpodobně výstup bez hlaviček odeslal !!
Zkus na to jít nějak takhle:
ob_start();
system("/var/makeAuthFiles/bin/makeAuthFiles $id", $file);
ob_end_clean();
// a tady by data toho souboru měly být v proměnné $file - tyhle data poslat s příslušnými hlavičkami http !!
Ale napsal jsem to z hlavy, nezkoušel jsem to!
Editoval m.brecher (19. 1. 2023 14:05)
- igi
- Člen | 24
@m.brecher
Díky, moc. Bylo to skutečně tím voláním system. Použil jsem
místo toho:
exec("/var/makeAuthFiles/bin/makeAuthFiles $id", $fileName);
$this->sendResponse(new FileResponse("/var/authFiles/$fileName[0]", $fileName[0], 'text/plain'));
Jen pro zajímavost, ten program v C++ vygeneruje soubor a uloží ho na disk. Jeho std výstup je jen právě název vytvořeného souboru. V budoucnu(jestli na to bude čas) mám v plánu to optimalizovat, že se bude generovat jen při změně v databázi, jinak se bude posílat vždy ten stejný soubor.
- m.brecher
- Generous Backer | 873
@igi
Díky, moc. Bylo to skutečně tím voláním system.
Ono to staré PHP je záludné, třeba ta funkce system() má ukázkově nepovedené api – magicky posílá na výstup návratovou hodnotu příkazové řádky, paralelně to samé předává do druhého PARAMETRU a vrací návratovou hodnotu, což NENÍ výstup toho cmd, jak by se očekávalo, ale jenom PRVNÍ ŘÁDEK – ha ha ha.
Jenom ostřílený php borec tohle použije správně :).
Editoval m.brecher (19. 1. 2023 17:00)