Jak vyzvednou soubor z databáze?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
fary
Člen | 155
+
0
-

Rád bych vyzvedl soubor z databáze (MySQL) ale nějak nevím, jak s pomocí Nette tohle udělat. Mám výběr z DB, který mám uložený v proměnné:

V presenteru:

$files = $this->context->fileRepository->findBy(array('mime_type' => 'application/pdf'));

A nemám tušení, jak např donutit prohlížeč ke stažení souboru na disk.

Oli
Člen | 1215
+
0
-

Já jsem nutil stáhnout soubor zhruba takhle:

public function actionDownload()
{
	header('Content-Type: application/octet-stream');
	header("Content-Transfer-Encoding: Binary");
	header("Content-disposition: attachment; filename=\"".$file."\"");
	readfile($destination);
	exit();
}
David Matějka
Moderator | 6445
+
0
-

musis poslat spravnou response, nette ma v sobe bohuzel jen pro soubory ulozene na disku – https://api.nette.org/…esponse.html Takze bys mohl ten soubor ulozit a poslat skrz tuhle response. Ja pouzivam upravenou response, kde jako prvni parametr neprijima nazev souboru, ale jeho obsah: https://gist.github.com/matej21/7975975

pak staci v presenteru:

$this->sendResponse(new ContentResponse($file->content, $nazevSouboru, TRUE /* nebo FALSE, pokud to chci zobrazit */, 'application/pdf'));
fary
Člen | 155
+
0
-

OK, díky. Nakonec jsem to tedy provedl tak, že jsem si pomocí $tmp = tempnam(APP_DIR . '/../temp', 'tmp') v aplikačním adresáři /temp vytvořil dočasný soubor a do něj jsem pomocí $res = fopen($tmp, 'w') zapsal obsah souboru z DB a pomocí fwrite($res, $file->file_content) jsem data zapsal. Pak jsem použil zmíněnou response:

$this->sendResponse(new Nette\Application\Responses\FileResponse(
	$tmp,
	$file->name . $file->extension,
	$file->mime_type));

a zavřel pomocí fclose($res);

Ještě jednou díky :-)

fary
Člen | 155
+
0
-

A pak ještě tedy smazat ten dočasný soubor unlink($tmp);

David Matějka
Moderator | 6445
+
0
-

no, kdyz nad tim ted premyslim, tak ten zpusob ulozeni do temp je komplikovanejsi – sendResponse totiz ukonci beh presenteru, tudiz pokud mas zavreni a smazani souboru za tim, tak se to neprovede. to mazani budes muset navazat na event onShutdown u presenteru – tedy nejak takhle:

public function actionDefault()
{
	$file = ...; //vybrat z db
	$tmp =  tempnam(..);
	$res = fopen(..);
	//zapsat a uzavrit
	$this->onShutdown[] = function() use($tmp) {
		file_exists($tmp) && unlink($tmp);
	};
	$this->sendRespone(new FileResponse(...));
}

ale jednodussi bude pouzit tu moji response :)