[addon file-downloader] File Downloader
- Honza Kuchař
- Člen | 1662
Diskuse ke stránce File Downloader
Ahoj, tak jsem vytvořil stránku v extras. Takže prosím svoje názory, postřehy, nápady a připomínky prosím pište sem. ;)
P.S.: Mám ještě dalších pár nápadů, jak to vylepšit. :)
- Jan Tvrdík
- Nette guru | 2595
Trochu jsme nepochopil, proč k tak poměrně jednoduché stránce tvoříš ilustrační video. Myslím, že všechno je jasné i bez něj.
- PetrP
- Člen | 587
michalh napsal(a):
Edit Pro Davida: šla by udělat nějaká konvence, aby všechny dema v extras byly na nette.org?
David už někde psal že by to bylo zbytečně složité (nebo tak ňák) a že bude jednoduší když si live dema budem dávat na svoje hostingy, které stejně všichni máme, ne?
- Honza Kuchař
- Člen | 1662
Takže k tomu videu: vrátil jsem ho zpět. Pravda informační hodnotu (zatím) nemá, ale připravím nové, kde už nějakou bude mít (jak se chová readfile a FileDownloader). (už mám skoro hotovou další verzi, která je kompletně překopaná – lépe logicky členěná a více jsem se snažil dodržovat coding-standard) nová verze bude členěná podobně jako třída Mail v nette. (tzn. zde budou Downloadery atd.)
- Honza Kuchař
- Člen | 1662
Takže ukázka z verze 1.0.0 beta. Dneska ji dám do repozitáře ke stažení.
Co se změnilo:
– Prakticky vše – kompletně přepsáno
– Opraveny nesmysly v názvech proměnných a metod (intuitivnější)
– Modulární systém (FileDownload,IDownloader a tzv. downloadery)
– Callbacky (BeforeDownloaderStarts
;
BeforeOutputStarts
; StatusChange
;
Complete
; ConnectionError
; Abort
;
TransferContinue
)
– Plně fluentní prostředí
– Vylepšená autodetekce mime-typu (když se zavolá setMimeType poté se
použije nastavený, jinak se provede autodetekce)
– Podpora pro defaults (viz ukázka bod 2)
Ukázka
- (volitelně) Zaregistrujeme downloadery – tyhle dva jsou zaregistrovány už ve FileDownload.php
FileDownload::registerFileDownloader(new NativePHPDownloader);
FileDownload::registerFileDownloader(new AdvancedDownloader);
Můžete si zaregistrovat svoje další downloadery (nejvyšší prioritu má ten poslední) nebo registraci zrušit pomocí:
FileDownload::clearFileDownloaders();
- (volitelně) Nastavíme výchozí hodnoty
FileDownload::$defaults["speedLimit"] = 10*FDTools::KILOBYTE;
- Pošleme soubor klientovi
- Fluentně
$file = FileDownload::getInstance()
->setSourceFile(dirname(__FILE__)."/temp/test-64MB.tmp")
->setTransferFileName("test ščř ščř ščř ščř.php")
->setSpeedLimit(5*FDTools::MEGABYTE)
->addBeforeDownloaderStartsCallback("onBeforeDownloaderStarts")
/* ... */
->download();
b) klasicky
$file = new FileDownload;
$file->sourceFile = dirname(__FILE__)."/temp/test-64MB.tmp";
$file->transferFileName = "test ščř ščř ščř ščř.php";
$file->speedLimit = 5*FDTools::MEGABYTE;
$file->onBeforeOutputStarts[] = "onBeforeOutputStarts";
/* ... */
$file->download();
- Honza Kuchař
- Člen | 1662
Ukázka callbacků (log) – 256MB soubor:
1. spojení – pozastaveno
onBeforeDownloaderStarts
onBeforeOutputStarts
onNewTransferStart
onStatusChange: 5242880bytes transferred
onStatusChange: 10485760bytes transferred
...
onStatusChange: 99614720bytes transferred
onStatusChange: 104857600bytes transferred
onConnectionError
onAbort
2. spojení pokračování
onBeforeDownloaderStarts
onBeforeOutputStarts
onTransferContinue
onStatusChange: 23068672bytes transferred
...
onStatusChange: 145096704bytes transferred
onComplete
Editoval honzakuchar (29. 6. 2009 10:53)
- Lopo
- Člen | 277
Call-time pass-by-reference has been deprecated in /home/…/app/extras/FileDownloader.php on line 362
@version $Id: FileDownloader.php 13 2009–06–25 16:35:50Z
PHP 5.2.10, Nette 0.9/398 nonprefix
pre istotu idem odskusat poslednu SVN verziu …
takze posledna SVN stable verzia:
Warning: Call-time pass-by-reference has been deprecated in
/home/…/app/extras/FileDownload.php on line 476
Editoval Lopo (2. 7. 2009 14:55)
- Honza Kuchař
- Člen | 1662
Mě si sice tahle chybka neprojevuje. Nicméně, zkus na tom řádku
362 změnit ty parametry fuknce bez toho &
. tzn:
self::_parseRangeHeader($req, $res, $req->getHeader("Range"), $size, $start, $end, $length);
//EDIT: Když vezmeš verzi z /trunk tak by se ta chyba neměla projevovat vůbec. (rev. 22)
P.S.: Na Mozille 3.5 nefunguje zapauzování stahování. Na opravě se už pracuje.
Editoval honzakuchar (3. 7. 2009 23:49)
- Honza Kuchař
- Člen | 1662
Vydána verze 1.0.0 RC1.
Opraveny výše zmíněné bugy. (Firefox 3.5 a dělení nulou)
Pozámka: příklad form velmi zatěžuje CPU serveru – ukládá do cache všechny volané callbacky a poté je zase vypisuje. Přidám tam v další rev. zaškrtávací políčko na vypnutí logování. (edit: už je to tam: rev. 27)
//EDIT: + nové příklady
Editoval honzakuchar (13. 7. 2009 13:30)
- Honza Kuchař
- Člen | 1662
Už je zaktualizovaná dokumentace File Downloaderu. Vytvořil jsem nové video.
- kutilm
- Člen | 21
Ahoj,
rád bych downloader použil pro posílání obrázků (ale nejen jich) do
prohlížeče, tak aby se zobrazili přímo v okně prohlížeče. Momentálně
to řeším vlastním downloaderem:
<?php
class MyDownloader extends AdvancedDownloader
{
protected function sendStandardFileHeaders(FileDownload $file,BaseDownloader $downloader=null)
{
parent::sendStandardFileHeaders($file,$downloader);
$res = Environment::getHttpResponse();
$res->setHeader('Content-Disposition', 'inline; filename="'.FDTools::getContentDispositionHeaderData($file->transferFileName).'"');
}
}
?>
Ale možná by se to dalo elegantněji řešit přímo na úrovni FileDownload? A kdyby ne, tak se třeba někomu hodí ten downloader:)
Jinak děkuji
Michal
- Honza Kuchař
- Člen | 1662
Jsem rád, že to někdo používá. :) Nicméně vlastní downloader není
potřeba, stačí si tu potřebnou hlavičku přepsat v callbacku. Sice jsem to
nezkoušel, ale neměl by být problém přepsat si hlavičky v callbacku
onBeforeOutputStarts
nebo
(zde se nastavené hlavičky znova
přepsaly hlavičkami downloaderu).onBeforeDownloaderStarts
$download = new FileDownload;
$download->onBeforeOutputStarts[] = "mojeHlavicky";
function mojeHlavicky(FileDownload $download,IDownloader $downloader){
Environment::getHttpResponse()->setHeader('Content-Disposition', 'inline; filename="'.FDTools::getContentDispositionHeaderData($download->transferFileName).'"');
}
Editoval honzakuchar (18. 7. 2009 19:50)
- Honza Kuchař
- Člen | 1662
Ano díval jsem se do kódu a opravdu je to tak. Omlouvám se za zmatek.
//EDIT: zkusím na tohle vytvořit nějakou zkratku ;)
Editoval honzakuchar (18. 7. 2009 19:51)
- David Grudl
- Nette Core | 8218
Možná by bylo zajímavé zkusit File Downloader upravit do podoby IPresenterResponse. Jde o úplnou novinku, jako ukázka velmi primitovního downloaderu by mohlo posloužit tohle.
- Honza Kuchař
- Člen | 1662
Když se podíváte do SVN, tak FileDownloader už umí IPresenterResponse. Použití je téměř stejné. (z examples/MVP)
$fileDownload = new AppFileDownload($this);
$fileDownload->sourceFile = __FILE__;
$fileDownload->speedLimit = 5*FDTools::BYTE;
$fileDownload->download();
nebo
AppFileDownload::getInstance($this)
->setSourceFile(__FILE__)
->setSpeedLimit(5*FDTools::BYTE)
->download();
nebo
$fileDownload = new AppFileDownload($this);
$fileDownload->sourceFile = __FILE__;
$fileDownload->speedLimit = 5*FDTools::BYTE;
$this->terminate($fileDownload);
Metoda download() volá Presenter::terminate(), takže aplikace které používají FileDownloader budou nyní podstatně lépe testovatelné.
Dále: opraveno pár bugů, které souvisí s přechodem na PHP 5.3
- Honza Kuchař
- Člen | 1662
Díky za upozornění. S aktuální verzí Nette FileDownloader nemám nikde spuštěný.
- Aurielle
- Člen | 1281
Nevím zda už to není opraveno, ale ve stable verzi (ze zipu) dělá na PHP 5.3 bordel eregi (deprecated), pak jeden warning u mime_content_type (když neexistuje transferFileName). A jak už bylo zmíněno tak deprecated getClass();
Poznámka – ve Firefoxu 3.6 se mi poslední chyba (deprecated getClass()) nechtěla ukázat, Firefox tvrdil že soubor byl nenalezen a hlavičky požadavku vracely 500. V IE byla chyba v Laděnce vidět.
- Honza Kuchař
- Člen | 1662
Stable verze je verze 1.0 na SVN je verze 1.1-rc, která už má podporu pro PHP 5.3. Je to verze RC. Ale nazval bych ji už stabilní. (dlouhodobě není žádná hlášená chyba)
Editoval honzakuchar (11. 4. 2010 13:30)
- Honza Kuchař
- Člen | 1662
Možná by i stačilo, kdyby se ti podařil sehnat nějaký příklad (jakýkoli soubor kdekoli na internetu), kde to funguje korektně, odchytili bychom hlavičky a viděli bychom co a jak.
- hrtlik
- Člen | 7
Tak vyřešeno s IE. Opravený kód v FDTools: http://pastebin.com/FLKKkGDs . Je tam přidáno
urlencode.
Opera nakonec háčky a čárky uměla, ale v tom příkladu je ukázka se
složenými závorkami a z nějakého důvodu to vynechá, nedokázal jsem to
vygůglit.
Editoval hrtlik (1. 9. 2010 20:26)
- Honza Kuchař
- Člen | 1662
Zahrnu to do distribuce, hned jak budu mít chvilku to otestovat.
;) Je to tam. Děkuji moc za spolupráci, jménem celé Nette
komunity!
Editoval Honza Kuchař (2. 9. 2010 8:33)
- Ondřej Kubíček
- Člen | 494
zdravím,
díky za file downloader, ale mam problem jej rozchodit. Stáhl jsem si z svn
nejnovější verzi (1.1.0rc) a firefox stále píše soubor nemůže nálezt.
V podstatě jak píše gmvasek. Jak to vyřešit? Používám PHP 5.3 a nette
ve verzi 1.
- Jendaaa
- Člen | 21
Zdravím,
můžete mi prosím někdo vysvětlit, v čem dělám chybu? Kód je
následující
<?php
...
public function download() {
\FileDownload::getInstance()
->setSourceFile($file)
->addCompleteCallback('complete')
->download();
}
public function complete(\FileDownload $download,\IDownloader $downloader)
{
Environment::getSession('key')->downloaded = true;
}
?>
problém je v tom, že callback se vůbec nevolá, protože session
downloaded se nezmění. Přitom soubor se v pořádku stáhne.
Díky
- redhead
- Člen | 1313
Protože musíš specifikovat, kde se to má volat. Tvůj příklad by volal globální funkci, nikoli metodu objektu.
Nevím jak je to tam přesně řešené, ale zkus:
->addCompleteCallback($this, 'complete')
//nebo
->addCompleteCallback(callback($this, 'complete'))
Spíš asi to druhý..
Editoval redhead (13. 12. 2010 21:22)
- Jendaaa
- Člen | 21
redhead napsal(a):
Protože musíš specifikovat, kde se to má volat. Tvůj příklad by volal globální funkci, nikoli metodu objektu.
Nevím jak je to tam přesně řešené, ale zkus:
->addCompleteCallback($this, 'complete') //nebo ->addCompleteCallback(callback($this, 'complete'))
Spíš asi to druhý..
Zkusil jsem oboje, bez úspěchu.
- Mikulas Dite
- Člen | 756
https://componette.org/search/?…:
Tzn. callbacky registrujeme buť onCallback[] = callback;
Zkontroluj, jesli registruješ validní callback (pokuď používáš
array()
). Jestli tam píšeš callback()
, tak se buď
nezavolá, protože je v addonu chyba, nebo proto, že se zavolat nemá –
zavolá se něco jiného, třeba onConnectionLost
místo
onAbort
nebo něco podobného.
Zkus svůj callback jinde, třeba na BeforeDownloaderStarts
–
jestli se tvůj callback zpustí, je chyba v triggeru.
Editoval Mikulas Dite (13. 12. 2010 22:08)
- Jendaaa
- Člen | 21
Mikulas Dite napsal(a):
https://componette.org/search/?…:
Tzn. callbacky registrujeme buť onCallback[] = callback;
Zkontroluj, jesli registruješ validní callback (pokuď používáš
array()
). Jestli tam píšešcallback()
, tak se buď nezavolá, protože je v addonu chyba, nebo proto, že se zavolat nemá – zavolá se něco jiného, třebaonConnectionLost
místoonAbort
nebo něco podobného.Zkus svůj callback jinde, třeba na
BeforeDownloaderStarts
– jestli se tvůj callback zpustí, je chyba v triggeru.
EDIT: Vyřešeno, zapomněl jsem na ten array()
Tak jsem zkusil zaregistrovat BeforeDownloaderStarts, ten už se spustí, ale laděnka mi hlásí: Callback ‚complete‘ is not callable. Takže u onComplete byla asi stejná chyba, která akorát kvůli odeslaným hlavičkám nebyla zobrazená…Teď akorát proč to nejde volat?
Editoval Jendaaa (17. 12. 2010 10:23)
- Honza Kuchař
- Člen | 1662
Callback complete, pokud se správně pamatuji, funguje pouze u driveru Advanced. Ale musím to ověřit. Píšu si to do diáře.
Ale pozor! Complete je jen pokud proběhne úspěšné stažení. Doporučuji se podívat na příklad v distribuci „form“. Kde se ukazjí volané callbacky.
Bude to vypadat přibližně takto, pokud se přeruší spojení – tedy žádný complete se nezavolá. Je to očekávané chování.
Con. #1294142943-5224 (Aborted)
5: onAbort: 50 B <->; position: 100 B; http-range: 0 B-8 MB; progress (con: 0% X file: 0%)
4: onConnectionLost: 50 B <->; position: 100 B; http-range: 0 B-8 MB; progress (con: 0% X file: 0%)
3: onStatusChange: 50 B <->; position: 50 B; http-range: 0 B-8 MB; progress (con: 0% X file: 0%)
2: onNewTransferStart: 0 B <->; position: 0 B; http-range: 0 B-8 MB; progress (con: 0% X file: 0%)
1: onBeforeOutputStarts: 0 B <->; position: 0 B; http-range: 0 B-8 MB; progress (con: 0% X file: 0%)
0: onBeforeDownloaderStarts: 0 B <->;
- Honza Kuchař
- Člen | 1662
Docela by mě zajímalo, kde byla chyba. Ale s tím complete je to tedy dobrý návrh. Protože by se mně samotnému líbil návrh toho, jak je to s jQuery, tedy
**success** = úspěšně dokončeno
**complete** = dokončeno jakkoli
**error** = chyba
…ale byl by to docela dost nepříjemný BC break, jste pro ho provést? (až bude alespoň 10 lidí pro nebo proti vynesu nějaký rozsudek, jak se tato věc bude mít dál)
- Honza Kuchař
- Člen | 1662
- Neměl by to být problém
- nesouvisí to s FileDownloaderem, ale s routováním
Routa by měla vypadat nějak takto:
new Route("<presenter downloads>/file/<fileId [0-9]>",array(
"action" => "download"
));
Ale je dost možné, že je to úplná blbost.
- klimax
- Člen | 7
jde nějakým způsobem uživatele informovat o tom, že se probehl nějaký
callback, tedy že spadlo stahování, stahování se úspěšně provedlo,
atd.?
nic, co je po
<?php
$filedownload->download();
?>
se již neprovede a v callbackach sice mam flashmessage, ale ty se neprovedou
<?php
public function onFileDownloadAbort(FileDownload $download, IDownloader $downloader) {
$this->flashMessage('Bylo přerušeno stahování souboru', 'error');
}
?>
provede se napriklad ulozeni informaci do DB, ale rad bych prave flashmessagi uzivatele informoval.