Smazání souboru po stažení

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

Zdravím všechny,

řeším pro mě zapeklitý problém, a to jak smazat soubor po jeho stažení. Pro stahování používám tento kód:

$this->sendResponse(new Nette\Application\Responses\FileResponse('websitecreator/' . $folder_name . '/final.zip'));

a potřeboval bych po tomto řádku smazat stahovaný soubor nebo si to přesměrovat na akci, která by vykonala smazání. Bohužel mi nefunguje ani samotné mazání přes unlink() ani přesměrování přes redirect, ale je mi jasné, že je to způsobené tím stahováním ale nevím jak toto vyřešit.

Díky za pomoc :)

Michal Vyšinský
Člen | 608
+
0
-

Ahoj,

nejspíš bude nejjednodudšší cesta vytvořit si vlastní FileResponse (klidně podědit Nette\Application\Responses\FileResponse) a po fclose($handle) zavolat unlink. Nicméně nevím, jestli je možné smazat soubor během stahování a také pak nebude funkční „redownload“ souboru.

Šaman
Člen | 2666
+
0
-

Asi bych to řešil oklikou, třeba nastavením příznaku na smazání a pravidelný cron, který vymaže všechny soubory, které už byly smazané před více, než nastavený čas.

MartinitCZ
Člen | 580
+
0
-

Také doporučuji řešení, které popsal @Šaman Když spadne připojení, nebo se pokazí soubor při stahování, a ty ho smažeš, tak má daný „stahovatel“ smůlu.

quiced
Člen | 85
+
0
-

No mě by nejvíce vyhovovalo, kdyby se ten soubor mazal hned, protože před stahováním se mi balí do zipu, tak bych nerad aby tam ty soubory nezůstávali, a to, že se pokazí stahováním nevadí, protože uživatel má možnost si celý zip znovu vygenerovat.

Tak jinak nešlo by to udělat tak, že bych zip neukládal, ale rovnou ho posílal ke stažení?

Pro zazipování používám tohle:

$zip = new \ZipArchive;
$zip->open($zip_name, \ZIPARCHIVE::CREATE);
$zip->addFile($file,$new_filename);
$zip->close();
Milo
Nette Core | 1283
+
-1
-

Můžeš zkusit register_shutdown_function().

quiced
Člen | 85
+
0
-

Milo napsal(a):

Můžeš zkusit register_shutdown_function().

Vyzkoušel jsem to ale bohužel to nefunguje. Zkoušel jsem jak register_shutdown_function(unlink()), tak i zápis přes funkci, ale ani jedna z verzí nebyla funkční.

Milo
Nette Core | 1283
+
0
-

Protože sendResponse() ukončí běh akce. Musíš to volat před tím, cca:

$file = 'path/to/file.zip';
$zip = new \ZipArchive;
...
register_shutdown_function(function() use ($file) {
	unlink($file);
});
$this->sendResponse(....);
quiced
Člen | 85
+
0
-

Milo napsal(a):

Protože sendResponse() ukončí běh akce. Musíš to volat před tím, cca:

$file = 'path/to/file.zip';
$zip = new \ZipArchive;
...
register_shutdown_function(function() use ($file) {
	unlink($file);
});
$this->sendResponse(....);

Tak bohužel stále mi to nefunguje i když jsem to dal přes sendResponse().

Milo
Nette Core | 1283
+
0
-

To je divné. Tak jak psal @MichalVyšinský, podědit FileResponse, přetížit send() a v ní unlink.

quiced
Člen | 85
+
0
-

Milo napsal(a):

To je divné. Tak jak psal @MichalVyšinský, podědit FileResponse, přetížit send() a v ní unlink.

A nešlo by to teda udělat tak, že bych ten zip neukládal, ale rovnou ho stáhl?

Majkl578
Moderator | 1364
+
0
-

Shutdown function se do kontextu Presenteru fakt moc nehodí. Spíš koukni sem: https://forum.nette.org/…quest-called

Milo
Nette Core | 1283
+
0
-

quiced napsal(a):

A nešlo by to teda udělat tak, že bych ten zip neukládal, ale rovnou ho stáhl?

Odeslání ZIPu s on-the-fly kompresí není úplně triviální. Jakub Vrána psal o tom, jak to dělal pro velké soubory. Možná by to šlo ještě vlastním wrapperem v paměti, ale to bude několikanásobně složitější.

Milo
Nette Core | 1283
+
0
-

Majkl578 napsal(a):

Shutdown function se do kontextu Presenteru fakt moc nehodí. Spíš koukni sem: https://forum.nette.org/…quest-called

@Majkl578 Máš pro to nějaké důvody, nebo je to jen pocit? register_shudown_function() nezatahuje další závislosti a je to přímočaré.

Majkl578
Moderator | 1364
+
0
-

Příjde mi to prostě z pohledu MVP/presenteru čistší než se hrabat v globálních shutdown handlerech.

quiced
Člen | 85
+
0
-

Tak díky za pomoc, zatím jsem vytvořil takové provizorní nicméně funkční řešení. Nechávám si vytvářet náhodné adresáře a poté je budu přes cron mazat.

voda
Člen | 561
+
0
-

Já úspěšně používám v presenteru tento kód:

file_put_contents($file, ...);
$this->netteApplication->onShutdown[] = function() use ($file) {
	unlink($file);
};
$this->sendResponse(new FileResponse(...));

netteApplication vyžaduji v konstruktoru.

pitr82
Člen | 121
+
0
-

Dobrý den,
rád bych se zeptal, jak v bootstrap.php zavolat službu v onShutdown ?

$container->getService('application')->onShutdown[] = function() use ($container){
        //[službu definovanou v config.neon]
	$container->sluzba->funkce(); // toto mi nefunguje nette 2.2.0
};

@voda : jak přesně zavoláš v konstruktoru netteApplication ?

Editoval pitr82 (24. 6. 2014 18:25)

David Matějka
Moderator | 6445
+
0
-

@pitr82: pokud se nepletu, tak ti to primo poradi, ze mas misto toho pouzit getService metodu :)

voda
Člen | 561
+
0
-

@pitr82: sorry za pozdní odpověď, nevšiml jsem si nové otázky.

Vyžaduji v konstruktoru, Nette se o předání postará:

class MyPresenter extends Nette\Application\UI\Presenter {
	/** @var \Nette\Application\Application */
	private $netteApplication;

	public function __construct(\Nette\Application\Application $netteApplication) {
		parent::__construct();
		$this->netteApplication = $netteApplication;
	}
}