MultiFileUpload Vaadin komponens fejlesztése

Posted by | · · · | Szoftverfejlesztés | Nincs hozzászólás a(z) MultiFileUpload Vaadin komponens fejlesztése bejegyzéshez

Beindultak a Vaadin-os projektek és elég hamar felmerült az igény egy fájl feltöltő komponensre. Körülnéztem, a már meglévő modulok között. A „gyári” Upload komponens sajnos kilőve, mert szükség volt arra a funkcióra, hogy a felhasználó egyszerre több fájlt is ki tudjon választani feltöltésre. A „gyári” Upload komponens pedig csak egy fájlt képes kezelni, amíg az fel nem töltődött teljesen, addig hiába választjuk ki a következőt.

vaadin-add-ons

A Vaadin Add-onok között kutatva találtam meg az EasyUploads komponenst. Ez első ránézésre megfelelt az általunk támasztott igényeknek. Lehetőség van egyszerre több fájl kiválasztására, akár a feltöltés közben is újabbak hozzáadására. Azon böngészőknél, amelyek nem támogatják a HTML5-öt (IE6, IE8, IE9, Opera), a komponens egy Flash-es fájl feltöltőre cserélte le önmagát.

Ami nekünk nagy hiányosság volt, az az, hogy ha már kiválasztottuk a fájlokat feltöltésre,  onnantól  kezdve már nem lehetett leállítani őket. Kinézetre pedig a Vaadin Sampler-ben lévő File Upload komponens demójához hasonlót szerettünk volna. Illetve a Flash-es verziót is szerettük volna elkerülni.
Elkezdtem hát elmélyedni az EasyUploads kódjában, hogy lehetne testre szabni a mi igényeinkhez. A kezdéshez konkrétan 3 fájlt tartottam meg belőle, a szerver oldali komponenst, a widgetet és az őket összekötő connector osztályt, a többit kipucoltam.

MultiFileUpload komponens fejlesztése

Feltöltés megszakítása

Először a fájlok feltöltésének megszakítását szerettem volna megoldani. A szerver oldali komponens egy  com.vaadin.server.StreamVariable interfészt implementál, amit a kliens oldalnak is elküld. Ez reprezentálja egy fájl feltöltésének folyamatát. Függvényei:

public void streamingStarted(StreamingStartEvent event)  //a fájl feltöltésekor ez hívódik meg először, az esemény többek között a fájl nevét, méretét tartalmazza
public OutputStream getOutputStream() //Stream, ahova a feltöltendő fájlt írjuk
public void onProgress(StreamingProgressEvent event) //feltöltés közben, rövid időközökkel hívódik meg, a feltöltés állapotát nyerhetjük ki az eseményből
public void streamingFinished(StreamingEndEvent event) //a feltöltés végén hívódik meg
public void streamingFailed(StreamingErrorEvent event) //sikertelen feltöltés esetén hívódik meg
public boolean isInterrupted() //amennyiben true értéket adunk vissza, a feltöltés megszakad

Az éppen feltöltődő fájl megszakítása így elég könnyen ment, csak true-t kellett visszaadnom a „Mégsem” gombra kattintáskor.

Mivel az EasyUploads-ban is lehetőség volt több fájl kiválasztására, már eleve kezelt egy listát, vagy nevezzük feltöltési sornak a szerver oldali és a kliens oldali kódban egyaránt. Annyit kellett módosítanom, hogy a fájlokat tartalmazó objektumokat ellátom egyedi azonosítóval a kliens oldalon, és a szerver oldalon lehetőséget biztosítok a feltöltési sorból történő, azonosító szerinti törlésre, amelyet a kliens oldallal is szinkronizálok. Így már lehetséges volt a feltöltési sorban várakozó fájlok megszakítása is.

Dinamikus feltöltő komponens

Mivel csak a HTML5 -öt támogató böngészők kezelik az egyszerre történő több fájl kiválasztását és kezelését, ezért el kellett döntenünk, hogy hogyan akarjuk kiváltani a régebbi, vagy nem támogatott böngészőkben ezt a problémát. A Flash-es verziót kerülni szerettük volna, ezért úgy döntöttünk, hogy a komponens a gyári feltöltőt fogja példányosítani. A CustomComponent leszármazott SmartMultiUpload wrapper osztály pont ezt teszi: amennyiben a böngésző támogatva van, egy MultiUpload, ellenkező esetben egy Upload komponenst hoz létre.

UI

multifileupload_display_crop

Az elképzelés szerint a File Upload demóhoz hasonló Window-ba megjelenítve szerettük volna látni a fájlok feltöltésének folyamatát. Az ablakban az éppen feltöltődő fájl állapotát egy ProgressBar segítségével és a feltöltött bájtok mennyiségének megjelenítésével (dinamikus mértékegység átváltással) reprezentálom. A feltöltési sor egy táblázatban jelenik meg, dinamikus táblázat mérettel. A feltöltések végeztével az ablak bezárul.

Első probléma akkor jelentkezett, amikor több ilyen komponenst raktunk ki egy nézetbe, mivel így mindegyik saját ablakot nyitott fel, ami elég csúnya és kezelhetetlen volt. Módosítottam a kódot, hogy egy ablak képes legyen több komponenst is kezelni. Az ablakban külön panelben jelennek meg az egyes komponenshez tartozó feltöltések. Így példányosításkor egy közös Window objektumot kell átadnunk a MultiFileUpload konstruktorának:

multifileupload_src

Ez az  UploadStateWindow egy UploadStatePanel listát tart nyilván, amelyek az egyes MultiFileUpload komponensekhez tartoznak.

Az UploadFinishedHandler interfész

public void handleFile(InputStream stream, String fileName, String mimeType, long length);

metódusát implementálva döntheti el a fejlesztő, hogy mit kezdjen a sikeresen feltöltött fájlokkal.
A 3. paraméter segítségével kikényszeríthetjük, hogy a SmartMultUpload osztály mindenképpen egy „gyári” Upload komponenst hozzon létre, ha nem akarjuk a többszörös feltöltést támogatni. Előnye, hogy a feltöltés állapotát így is nyomon követhetjük a közös ablakban.

UploadReceiver

A komponens tartalmaz egy UploadReceiver implementációt, amelyet a fejlesztő lecserélhet bármely másra. Ezen az interfészen keresztül történik az éppen feltöltött fájlok stream-elése. Az alap implementáció egy, a szerveren lévő ideiglenes temp fájlba menti a fájlt, melyet a feltöltés végeztével – függetlenül, hogy sikeres vagy sikertelen volt – eltávolít a fájlrendszerből.

Összefoglalás

A MultiFileUpload segítségével egyszerűen tudunk egyidejűleg több fájl kiválasztására és feltöltésére alkalmas komponenst létrehozni Vaadin alkalmazásunkban. A fájlok automatikusan egy design-os ablakba kerülnek, melyben a feltöltés állapotát követhetjük nyomon vagy akár meg is szakíthatjuk bármelyik fájl feltöltését.

image001_e
A MultiFileUpload Add-on megtalálható a publikus Vaadin Directoryban.

A forráskód pedig egy GitHub repositoryban.


No Comments

Leave a comment