Forms\ FileUpload: více souborů, multiple a to včetně getValue() – téměř hotovo
- bojovyletoun
- Člen | 667
Ahoj, mám nápad na vylepšení podpory
<input type=file multiple>
.
- Změna: metoda
addFile
a konstruktorFileUpload
má další bool parametr. - Je-li true, pak přidá atribut
multiple=„multiple“ a jméno prvku ve tvaru
file[]
. - příslušná hodnota formulářového prvku je pole s HttpUploadedFile (samozřejmě pokud bylo v konstruktoru true)
- vyřešeny validátory validate_***, ale ještě ne isfilled.
- Gist
Otestováno
Způsob testu:
- 1 pole s multiple – nahrány 2 soubory
- 1 pole s multiple – nahrány další 2 soubory (kontrola promíchání)
- 1 pole s multiple – nahrán další 1 soubor (kontrolola, zda jde o pole a ne o HttpUplFile)
- 1 pole bez multiple – nahrán další 1 soubor (kontrola zachování funkčnosti)
Prohlížeče (aneb za to nemůžu)
- Firefoxu 3.6 – 100% funkčnost
- Safari 5 Win – 100% funkčnost
- Chrome (dnešní) – 100% funkčnost
- Opera verze 11.10 (build 2005, 17.2.2011) a vyšší OK 100%
- Opera do verze 9,10,11.01 funguje, ale spotřebuje se navíc asi 4× víc RAM(což ale nezpůsobila moje úprava!), než je dat –podrobnosti v dalších postech.
- IE: 4% V dialogu se mi nepovedlo vybrat víc souborů, ale jinak to funguje OK.
Pak stačí přidat do FormContainer
function addFileMulti($name, $label = NULL){
$control = new FileUploadMulti($label);
return $this[$name] = $control;
}
Příklad výstupních hodnot
Nette\ArrayHash(3) ▼ {
"multi" => array(2) ▼ [
0 => Nette\Web\HttpUploadedFile(5) ▼ {
"name" private => "Windows7.full.iso" (13)
"type" private => NULL
"size" private => 208922827
"tmpName" private => "C:\web\php\tmp\php5579.tmp" (26)
"error" private => 0
}
1 => Nette\Web\HttpUploadedFile(5) ▼ {
"name" ...
}
]
"multi_vybran_jeden_soubor_" => array(1) ▼ [
0 => Nette\Web\HttpUploadedFile(5) ▼ {
"name" ...
}
]
"single" => Nette\Web\HttpUploadedFile(5) ▼ {
"name" ...
}
}
K diskuzi je
- případně mi poradit, proč v IE to zase nejde
- zvážit parametry min a max
- způsob validace (Image, MaxSize, Mime) (hardcoded nebo
nastavitelné?)
- pokud jen jeden soubor nevyhovuje, pak se vyhodí error (a data jsou zahozena)
- nevyhovující soubory jsou (tiše) vyjmuty
Editoval bojovyletoun (14. 3. 2011 23:32)
- Filip Procházka
- Moderator | 4668
git si rozhodně nainstaluj :)
Stručný návod jak přispívat:
1) registrace na github → fork na https://github.com/nette/nette
# stáhnout nette
$ git clone git://github.com/bojovyletoun/nette.git
# vytvoření nové větve
$ git checkout -b feature-multiple-file-upload master
provedeš úpravy..
# uložit všechny změny
$ git commit -a -m "Multiple file upload"
# nahrát na github
$ git push origin feature-multiple-file-upload
na githubu vlevo pod Source si klikneš na svoji větev feature-multiple-file-upload a vpravo nahoře Pull Request a budeš doufat :)
- bojovyletoun
- Člen | 667
OK, dal jsem pull. Jen mě trápí, jak sloučit 2 commity (přes rozhraní githubu)). Editoval jsem to přes web, takže tam mám commit pro Formcontainer.php a commit pro Fileupload.php
Editoval bojovyletoun (11. 3. 2011 0:13)
- Honza Marek
- Člen | 1664
A co když na formulářový políčko nastavíš validaci podle mime typu třeba? To bude taky asi potřeba upravit, ne? Pak to užitečné beze sporu bude.
- bojovyletoun
- Člen | 667
Tak jsem validaci přidal tak, že validační funkce jsem prefixoval _ a funkce callStatic jim podsune Objekt FileUpload s upravenou hodnotou value… Pak to běží přes foreach, dosadí se zpátky původní pole souborů a testuje se výsledné pole na výskyt false..
Jen jsem ještě neošetřil isFilled.
Dál, je možné nějak spojit commity do jednoho? Když nedám pull request,
jakým příkazem se t dá do hlavní větve.
zdroj
FileUpload, zdroj
FOrmcontainer
- jtousek
- Člen | 951
Hezká práce. :)
Popravdě ale raději soubory používám jinak. Když už totiž nějaký soubory nahaješ (i třeba dříve) tak u normálního fileuploadu není možnost je smazat, což uživatelé potřebují. Proto jsem upload souborů přesunul mimo formuláře a řeším to tímhle. Výhodou je drag&drop upload ve FF a Chromu.
- Ondřej Mirtes
- Člen | 1536
Spojit více commitů do jednoho můžeš na svém počítači pomocí
git rebase
a na GitHub je promítnout do té samé větve pomocí
git push --force
.
- Filip Procházka
- Moderator | 4668
On se evidentně snaží vyhnout tomu, aby to musel stahovat na svůj pc :)
- bojovyletoun
- Člen | 667
tak u normálního fileuploadu není možnost je smazat, což uživatelé potřebují. Proto jsem upload souborů přesunul mimo formuláře
Na valums uploader jsem se díval, je to pěkná věcička. Jenže myslím, že rozdíl je tam vidět: valums je nahrávač souborů se vším všudy (progress,javascript,komponenta) a tohle je čistě (lowlevel) rozšíření. Pokud to v prohlížeči nefunguje, tak je možnost si tam ručně přidat skriptík, který po přidání souboru přidá další input – na serveru se to interpretuje správně.
Ještě chci vyřešit věci: (kód v 1. příspěvku – odkaz na gisthub)
- možná přesun do vlastní třídy -HOTOVO
- dodělat validaci hotovo (neumí min, max)
- pokusit se o podporu pro Opery (pomocí tmpfile() a new HttpUploadFile)
Editoval bojovyletoun (11. 3. 2011 15:04)
- bojovyletoun
- Člen | 667
Takže už to funguje i v prohlížečích, které posílají multipart/mixed, což je Opera(9,10,11, kromě 11.50).
Dobré zprávy (multipart/mixed – Opera)
- soubory se tvoří přes tempnam() a pracuje se s nimi jako s ostatními nahranými soubory, soubory jsou automaticky mazány přes register_shutdown_function – funguje OK, i když nastane chyba skriptu
- data jsou čteny přes $_POST, takže binární data zůstanou nezměněna. PS:Netestováno na Linuxu. Také nevím, co se stane se zapnutými gpc
- moje úprava má zanedbatelnou spotřebu prostředků
"Špatné zprávy (multipart/mixed – Opera)
dochází k obrovské spotřebě prostředků:
- Jen samotné nahrání na server, bez načtení frameworku
- CPU: nevím jak zjistit, tipuji 1MB dat → 50ms
- RAM: 1MB dat → 3MB RAM
- s frameworkem
- CPU: 1MB dat → 100ms
- RAM: 1MB dat → 4MB RAM
Tedy jen samotné nahrání na server je problém, čisté PHP si vzalo pro 7MB dat 22MB paměti.
Editoval bojovyletoun (13. 3. 2011 13:02)
- bojovyletoun
- Člen | 667
myslíš spotřebu paměti? Je to obecně problém posílání velkého množství dat přes POST . U normálních prohlížečů se to taky samozřejmě posílá přes POST(ale multipart/formdata), jenže nějaký filtr(možná už i webserver?) předtím na vstupu rozpozná multipart/formdata a „přesune“ je do $_FILES, takže pak neprochází nějakými dalšími filtry(které tak žerou paměť). No a multipart/mixed nenajde, takže zůstanou v $_POST.
V Opeře 11.50 už posílá normálně. Když vyberu hodně dat (nad 10MB – podmínka, je že musí být v jednom inputu vybrány aspoň 2 soubory), tak stránka prostě nereaguje po odešlání formu.
Otázka je, zda to nechat jako experimentální. Ostatně stačí si zakomentovat 2 řádky, a bude se to chovat, jako by byl soubor nenahrál.
OT: na myego se píše o Ajaxovém nahrávání obrázků. Myslí se tím XMLHttpRequest 2? Ten totiž už prý umí nahrávat soubory. Nebo je tím myšlen iframe nabo snad flash?
Editoval bojovyletoun (13. 3. 2011 13:22)
- jtousek
- Člen | 951
Firefox a Chrome umí posílat soubory přes xmlhttprequest, Opera ne.
Btw. Opera (starší než 11.50) si nebere mime-type z form action? Nějak nechápu odkud bere to multipart/mixed. Nešlo by Operu přinutit aby použila co má?
Nakonec na tom ale až tolik nezáleží. Uživatelé opery většinou rychle aktualizují takže tolik nevadí, že to funguje jen v nejnovější.
- bojovyletoun
- Člen | 667
Zkoušel jsem FF a chrome, přes ajax to nejde. Možná je potřeba použít něco jako XMLHttpRequest2(), ale dnes nemám náladu na javascript.
Ve zdrojáku je enctype="multipart/form-data"
, ale je to
k ničemu.
S těmi aktualizacemi je to pravda (zvlášť u Opery) a navíc je to okrajový problém a Opera má fakt málo lidí.
Ještě malý benchmark: 30MB souborů: Opera: 3600ms, 160MB, v jiných prohlížečích standartní.
Jo ještě chci dodat, že je vždy možnost(hlavně pro IE) si dopsat skriptík, který třeba na onchange za aktuální input připojí nový a soubory naklikat po jednom. V opeře se to pak chová normálně.
Nehodí se to spíš do extras?
Pak bych měl ještě otázku: Co považujete za lepší v případě, že má prvek pravidlo (např MAXsize):
- klasicky: pokud je jeden přesáhne velikost, přidá se chyba (a data se zahodí)
- ty soubory, které budu větší se (tiše) vyfitlrují
Editoval bojovyletoun (14. 3. 2011 22:57)