Autor Zpráva
dtx
Profil *
Zdravím,

jakým způsobem řešit v php problém stahování souboru z cizího serveru XY, ukládání na lokální disk a zároveň posílání téhož souboru klientovi, který si ho vyžádal?

Situace je taková, že budu mít web, kde bude např. seznam souborů vyskytujících se na ****** s možností stažení. Jenže když návštěvník klikne na nějaký odkaz, nepřesměruje ho to přímo na soubor na ******, ale script by ho měl začít z ****** stahovat k sobě na disk, odkud ho by ho měl hnedka zase posílat dál návštěvníkovi - vše realtime. Návštěvníkovi bude tedy normálně zobrazen dialog pro uložení souboru a soubor se k němu bude muset ukládat po celou dobu, co tahám data ze sereru XY, který mi ten film poskytl.

Pro snazší pochopení principu fungování aplikace přikládám stručný náčrt procesu vyžádání/poslytnutí souboru
http://imagelink.cz/images/stream.png

Dá se toho vůbec nějak dosáhnout?

Co jsem tak zatím experimentoval, tak script poslal klientovi vždy jen tu část souboru, co byla zrovna u mě na disku uložena a uživatel tak obdržel nekompletní soubor. Bohužel se mi na to nepodařilo vygooglit žádný funkční příklad, tak jestli má někdo nějaký nápad, budu vděčný za každou radu.
dtx
Profil *
No, tak trošku mi to zcenzurovalo název toho serveru, který jsem uvedl jako příklad pro stahování. Přiložený obrázek ale mluví za vše, jde ale obecně o servery tohoto typu, zrovna u1oz.t0 se to pravděpodobně týkat nebude.
Alphard
Profil
Jestli nedostanete lepší odpověď, tak File Downloader pro Nette mj. umožňuje nastavení rychlosti. Možná by vás mohlo dále nasměrovat, konkrétněji bohužel nevím.
dtx
Profil *
Alphard: díky, určitě vyzkouším (jestli zjistím, jak tento doplňek/komponentu "nainstalovat", nějak s tím mám obecně problémy).

Pak mě ještě napadlo použít linuxí příkaz wget, který umí s parametrem -c "dotahovat" nedokončené soubory.. tak snad na něco přijdu a dám sem odpověď, pro příští generace :)

Jinak otázka je kdyžtak stále aktuální, kdyby měl náhodou ještě někdo nějaký nápad.
Krakatoa
Profil
dtx:
Nechápu proč by to někdo stahoval přes tvůj server, když to jde udělat i přímo? Aby link odkazoval přímo na soubor na tom download serveru.
dtx
Profil *
Krakatoa: mě se neptej, z mojí hlavy to není, vymyslel si to zaměstnavatel.

Ono to bude ještě trochu složitějši - u nás totiž budou dvě mašiny - jeden webserver, na kterém poběží web. rozhraní a pak mašina, která bude sama o sobě ty soubory stahovat. Takže já vlastně při požadavku na nějaký soubor od klienta nechám ten soubor vyhledat na fileshare serverech, seznam odkazů nabídnu uživateli, pokud na nějaký klikne, tak vybraný odkaz předám té naší druhé stahovací mašině, ta to začne stahovat z fileshare serveru, zároveň posílat mě a já to začnu zároveň přeposílat uživateli. Ani vlastně nevím, jestli je v PHP něco takového možné, taky mi to přijde až obskurně složitý, ale šéfstvu to asi holt nevymluvím.
TomášK
Profil
dtx:
Druhá mašina tedy má sloužit jako cachovací server? To možná není ani tak zavrženíhodné. Jednodušší než ukládat a posílat uložené mi přijde předávání načtených dat do dvou streamů:
while(buffer = getData("fileshare.server.com")) {
    putData(buffer, localFile);
    putData(buffer, userStream);
}

Ve výsledku bude mít data uživatel i budou uložená v souboru, jen postup není přesně ten, jaký popisujete. Problém tohoto přístupu je ten, že se stahováním dalšího bloku dat se čeká než se odešlou, což by šlo řešit asyncrhonními I/O operacemi, ale netuším, jestli php o něčem takovém někdy slyšelo.
dtx
Profil *
TomášK: Tak tak, ten druhý server bude vlastně cachovací. Že ten mnou zmiňovaný postup není správný je docela dost možný, protože jsem nikdy nic takovýho nedělal a tento postup byl první (a vlastně jediný), který mě napadl.

Ten vámi navrhovaný příklad ukládání v jednom streamu a zároveň posílání z cachovacího serveru do webserveru je ale vlastně stejný problém, jako řeším doteď - tedy jak v PHP na webserveru přebírat z cizího (v tomto případě tedy cachovacího) serveru nějaká data a zároveň je posílat ihned dál klientovi, i když nejsou ani na tom cachovacím serveru zatím kompletní. Už jsem vyzkoušel tuny příkladů, ale vždycky to klientovi buď

a) nabídlo sice soubor ke stažení hned, ale stáhla se jen aktuální část, která byla na cachovacím serveru v době požadavku
nebo
b) klientovi se zobrazilo okno "Uložit jako.." až v momentě, kdy byl soubor na cachovacím serveru kompletní a pak teprve začalo samotné stahování.

Takže jistojistě dělám něco strašně špatně :) Můžete prosím uvést nějaký konkrétní příklad, odkaz na příklad, nebo prostě obecný postup, jak se toto řeší? Už jsem z toho trošičku zoufalý a jakýkoliv nakopnutí správným směrem by mi snad trochu ulevilo.
Krakatoa
Profil
dtx:
Napiš mi prosím důvod, proč řešit ten download přes tvůj server a ne přímo:
- "Takže já vlastně při požadavku na nějaký soubor od klienta nechám ten soubor vyhledat na fileshare serverech, seznam odkazů nabídnu uživateli, pokud na nějaký klikne..."
- tak se na serveru nebo na klientu vygeneruje přímý link na soubor na fileshare serveru a stahování bude klient - fileshare server ... nechápu proč to má jít přes nějaký cache server?

Co se týče toho divného postupu přes cache server, nejde to udělat nějak pomocí curl? Já zkoušel curl u desktopové aplikace (zkoušel jsem si dělat stahovač souborů ze serveru s možností přerušovaného spojení) a curl má všelijaké možnosti na zjištění kolik se toho stáhlo a tak, tak když se pošle klientu skutečná velikost souboru a pak nějakým omezovačem (myslím, že v php jsou omezovače rychlosti) posílat jen tolik dat, která už tam jsou, tak by to šlo? Já se v tom moc nevyznám, nikdy jsem nic neudělal, jsem jen teoretik :-)
dtx
Profil *
Krakatoa: jak říkám, je to myšlenka zaměstnavatele, já jsem jen část řetězce. Na starosti mám pouze webové rozhraní a komunikaci s fileshare/cache serverem, samotný cache server už řeší někdo jiný (naštěstí, stahování a řešení captchy na fileserverech bych řešit nechtěl:) A projekt už je rozjetý, takže to asi jinak udělat nepůjde. Proč to chce šéfstvo stahovat na náš disk opravdu nevím. Asi mají hodně volných disků (o čemž pochybuju), nebo se pak rádi hrabou v tunách dat, jestli nenajdou něco zajímavýho :) opravdu netuším. Zítra máme poradu, tak to zkusím vysondovat a dám jen tak pro zajímavost vědět.

Jinak díky za tip na curl, tímhle směrem jsem se neubíral, ale za zkoušku to stojí.
TomášK
Profil
Krakatoa:
Cache server dává smysl, až si to někdo bude stahovat podruhé - zjistí se, že je to uložené a není potřeba to stahovat znovu zvenčí.

dtx:
Soubor, který bude stahovat (bude se mu zobrazovat v adresní řádce) nebude stahovaný soubor, ale php skript, viz např. thttp://www.linuxsoft.cz/article.php?id_article=310.

Vypadat to bude asi takto, nevyzkoušené.
<?php
header("Content-Description: File Transfer");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=\"soubor.txt\""); 

$handle = fopen("http://www.example.com/soubor.txt", "rb");
$local = fopen("/var/www/cache/soubor.txt", "w");
while (!feof($handle)) {
  $contents = fread($handle, 8192);
  fputs ($local, $contents);
  echo $contents;
}
fclose($handle);
fclose($local);
?>


Edit: opraven mód pro otevření souboru
Krakatoa
Profil
TomášK:
Asi tam má být w, ne? A lepší by to bylo s Content-Length, ať to nevypadá divně.

"Cache server dává smysl, až si to někdo bude stahovat podruhé - zjistí se, že je to uložené a není potřeba to stahovat znovu zvenčí. "
Cache server smysl nedává, když si to můžu stahovat z toho původního serveru. Stahuju z toho vzoroveho share serveru (a to bez captche) a žádný problém tam nemám, proč bych měl použít jako toto? Jestli si chcou udělat svůj share server, tak proč si tam ty soubory nenatahají zrovna? Já to fakt nechápu. Ale budiš, nemusím chápat všechno.
TomášK
Profil
Krakatoa:
Asi tam má být w, ne? A lepší by to bylo s Content-Length, ať to nevypadá divně.
w opraveno. Co se posílá za hlavičky, nevím, zkopíroval jsem to. Content-Length zní ale docela rozumně, ale nejde triviálně doplnit - je potřeba ji nejdřív načíst ze zdrojového serveru.

Cache server smysl nedává, ..
Představte si situaci, že jde o aktualizace sofrwaru (třeba Windows) ve firmě. Aktualizace patrně bude chtít víc lidí. Když si je stáhne první člověk, uloží se do cache na lokálním serveru. Druhý člověk z jiného PC si je bude chtít stáhnout, cache server zjistí, že už je má a poskytne je daleko rychleji než kdyby si je musel tahat zvenku z aktualizačního serveru.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: