|
Darmowy program Fileuploader napisany w JavaFX, dzięki któremu można ładować pliki na serwer bez potrzeby przeładowywania strony. Współpracuje praktycznie z każdą technologią webową (jsp, php itp). Posiada pasek postępu oraz wysyła komunikaty o stanach transferu poprzez funkcje JavaScript. Umożliwia ładowanie plików o dużych rozmiarach (dzieli plik na części). Rygory bezpieczeństwa utrzymuje się po stronie serwera - zwiększa to poziom bezpieczeństwa (program bez odpowiednich skryptów na serwerze jest bezużyteczny). Program jest bardzo łatwy w użyciu i konfiguracji.
Licencja: Aplikację można wykorzystywać i rozpowszechniać bez ograniczeń! Aplikacja zawiera obcy kod algorytmu Base64 dostępny na stronie http://iharder.net/base64.
Pobierz program:Download 20091201 zmiany: dołożona obsługa parametru specialData - przekazywanie treści z aplikacji (poprzez plik JNLP) do wyzwalaczy oraz serwera.
Starsze wersje: Download 20091128 Zapraszam do zaglądania na tą stronę. W przyszłości umieszczę na niej skrypt w PHP oraz demo aplikacji. Sposób użycia.1. Instalacja aplikacji wewnątrz kodu HTML.Aby Uploader był widoczny na stronie należy wewnątrz kodu HTML umieścić poniższy skrypt: <script src="http://dl.javafx.com/1.2/dtfx.js"></script> <script> javafx( { archive: "Uploader.jar", draggable: true, width: 255, height: 65, code: "com.j_ch.app.uploader.Main", name: "Uploader" } ); </script> |
Argument archive wskazuje na aplikację (Uploader.jar). Może być to dowolna ścieżka HTTP. Należy także pamiętać o umieszczeniu aplikacji czyli pliku Uploader.jar w odpowiednim katalogu. Wyzwalacze - funkcje JavaScript wywoływane w kluczowych momentach transferu pliku na serwer - umieszcza się wewnątrz tego samego kodu HTML i powinny mieć postać jak poniżej: /** * Transfer zakończony sukcesem * @param jfxuFileName Nazwa pliku * @param jfxuFileSize Rozmiar pliku w bajtach * @param jfxuUniqKey Unikatowy kod otrzymany z serwera * @param specialData Dane przekazane do uploadera */ function jfxuSuccess(jfxuFileName, jfxuFileSize, jfxuUniqKey, specialData) { } /** * Transfer został przerwany * @param jfxuFileName Nazwa pliku * @param jfxuFileSize Rozmiar pliku w bajtach * @param jfxuUniqKey Unikatowy kod otrzymany z serwera * @param specialData Dane przekazane do uploadera */ function jfxuStop(jfxuFileName, jfxuFileSize, jfxuUniqKey, specialData) { }
/** * Rozpoczęcie transferu * @param jfxuFileName Nazwa pliku * @param jfxuFileSize Rozmiar pliku w bajtach * @param jfxuUniqKey Unikatowy kod otrzymany z serwera * @param specialData Dane przekazane do uploadera */ function jfxuStart(jfxuFileName, jfxuFileSize, jfxuUniqKey, specialData) { }
/** * Wybrano plik do przesłania * @param jfxuFileName Nazwa pliku * @param jfxuFileSize Rozmiar pliku w bajtach * @param jfxuUniqKey Unikatowy kod otrzymany z serwera * @param specialData Dane przekazane do uploadera */ function jfxuSelect(jfxuFileName, jfxuFileSize, jfxuUniqKey, specialData) { }
|
Opis funkcj JS: - jfxuSuccess - gdy transfer zakończy się sukcesem,
- jfxuStop - gdy transmisja zostanie przerwana przez użytkownika (poprzez kliknięcie na STOP podczas transmisji pliku),
- jfxuStart - aplikacja rozpoczyna transmisję pliku,
- jfxuSelect - wybrano plik do przesłania (serwer zaakceptował plik).
Nie ma potrzeby definiowania wszystkich funkcji JavaScript. Można całkowicie pominąć ten etap jeżeli nie podamy nazw funkcji w pliku konfiguracyjnym. Aplikacja wywoła tylko funkcje zdefiniowane. Nazwy funkcji mogą być inne niż te pokazane wyżej, należy tylko pamiętać żeby określić ich prawidłowe nazwy w pliku konfiguracyjnym.
2. Konfiguracja aplikacji.Tutaj przyda się trochę wiedzy o JavaFX. Ja umieściłem konfigurację w pliku Uploader_browser.jnlp ale można umieścić ją w skrypcie wywołującym aplet. Plik Uploader_browser.jnlp jest wymagany do uruchomienia aplikacji. Dla ułatwienia należy go umieścić w tym samym miejscu co plik z aplikacją czyli Uploader.jar. <?xml version="1.0" encoding="UTF-8"?> <jnlp spec="1.0+" codebase="http://localhost:8082/servlet/org.netbeans.modules.javafx.project.JnlpDownloadServlet/D%3A/moje_projekty/JavaFX/Uploader/dist/" href="/Uploader_browser.jnlp"> <information> <title>Uploader</title> <vendor>Jacek Chojnacki -
Adres poczty elektronicznej jest chroniony przed robotami spamującymi. W przeglądarce musi być włączona obsługa JavaScript, żeby go zobaczyć.
</vendor> <homepage href="/index.php/myprojects/fileuploader.html"/> <description>Uploader</description> <offline-allowed/> <shortcut> <desktop/> </shortcut> </information> <security> <all-permissions/> </security> <resources> <j2se version="1.5+"/> <extension name="JavaFX Runtime" href="http://dl.javafx.com/1.2/javafx-rt.jnlp"/> <jar href="/Uploader.jar" main="true"/> </resources> <applet-desc name="Uploader" main-class="com.sun.javafx.runtime.adapter.Applet" width="255" height="65"> <param name="MainJavaFXScript" value="com.j_ch.app.uploader.Main"/> <param name="baseUrl" value="http://localhost:8080/WebBase/uploader.htm"/> <param name="buferSize" value="512"/> <param name="jsFuncSuccess" value="jfxuSuccess"/> <param name="jsFuncStop" value="jfxuStop"/> <param name="jsFuncStart" value="jfxuStart"/> <param name="jsFuncSelect" value="jfxuSelect"/> <param name="specialData" value="Test danych w parametrze: specialData"/> </applet-desc> <update check="background"> </jnlp>
|
Tutaj należy zwrócić uwagę na poszczególne tagi i argumenty: - tag jnlp argument codebase - należy zmodyfikować według własnych potrzeb czyli wskazać adres do katalogu, w którym znajduje się plik Uploader_browser.jnlp,
- tag resources / jar - href musi wskazywać na aplikację (Uploader.jar) - jeżeli aplikacja nie znajduje się w tym samym miejscu co plik Uploader_browser.jnlp należy podać ścieżkę do pliku Uploader.jar,
- tag applet-desc / param parametr baseUrl - value musi zawierać ścieżkę do skryptu, który ma obsłużyć transfer danych po stronie serwera (skrypt php, jsp lub inny),
- tag applet-desc / param parametr buferSize - value musi zawierać wielkość pojedynczej paczki przesyłanej na serwer w bajtach jako HTTP / POST,
- tag applet-desc / param parametry jsFuncSuccess, jsFuncStop, jsFuncStart, jsFuncSelect (NIE SĄ WYMAGANE) - poszczególne value powinny zawierać dowolne nazwy funkcji JavaScript (patrz na pt 1 wyzwalacze),
- tag applet-desc / param parametr specialData (NIE JEST WYMAGANY) - value może zawierać dowolną wartość przekazywaną do serwera oraz wyzwalaczy.
3. Skrypt po stronie serwera.Można wykorzystać dowolny serwer HTTP taki jak: Apache, Tomcat, GlassFish, JBoss i inne. Poniższy przykład przedstawia kod JSP, który wykorzystuję na serwerze Tomcat 6.0. <%@page contentType="text/html" pageEncoding="UTF-8" import="java.io.*"%><% int LIMIT_FILE_SIZE_B = 2*1024*1024; // 1M - maksymalny rozmiar pliku // -- przesyłane dane -- String jfxuOperation = request.getParameter("jfxuOperation"), jfxuSpecialData = request.getParameter("jfxuSpecialData"), // wartość z uploadera do wyzwalaczy oraz serwera - definiowana w pliku JNLP jfxuFileName = request.getParameter("jfxuFileName"), jfxuFileSize = request.getParameter("jfxuFileSize"), jfxuUniqKey = request.getParameter("jfxuUniqKey"), jfxuStatus = request.getParameter("jfxuStatus"), jfxuOffset = request.getParameter("jfxuOffset"), jfxuData = request.getParameter("jfxuData"), d_time = request.getParameter("d_time"); // -- czy komunikacja z uploaderem -- if(jfxuOperation==null) { out.print("false"); return; } // -- poszczególne operacje -- if(jfxuOperation.equals("checkFile")) { long fileSize = Long.valueOf(jfxuFileSize); if(fileSize>LIMIT_FILE_SIZE_B||!jfxuFileName.endsWith("pdf")) { out.print("false;Za duży rozmiar lub niedozwolone rozszerzenie pliku!"); return; } out.print("true;"+(new java.util.Date().getTime())); return; } // -- transmisja danych -- if(jfxuOperation.equals("dataFile")&&jfxuData!=null) { byte [] bytes = com.j_ch.utils.Base64.decode(jfxuData,com.j_ch.utils.Base64.URL_SAFE); File file = new File("D:\\\\"+jfxuFileName); // -- status paczki -- if(jfxuStatus.equals("begin")) { // pierwsza paczka if(file.isFile()) file.delete(); } else if(jfxuStatus.equals("progress")) { // kolejna paczka } else if(jfxuStatus.equals("end")) { } // ostatnia paczka // -- zapis pliku na serwerze -- OutputStream os = new FileOutputStream(file,true); try { os.write(bytes); } catch(Exception e) { out.print("false;jfxuOffset:"+jfxuOffset+" ["+e+"]"); os.close(); return; } os.close(); out.print("true"); return; } // -- transmisja przerwana -- if(jfxuOperation.equals("stop")) { File file = new File("D:\\\\"+jfxuFileName); // -- sprzątanie -- if(file.isFile()) file.delete(); } %>
|
Parametry przekazywane z uploader: - jfxuOperation - operacje (checkFile - sprawdź plik, dataFile - zapisuj dane, stop - operacja przerwana),
- jfxuFileName - nazwa pliku,
- jfxuFileSize - rozmiar pliku w bajtach,
- jfxuUniqKey - unikatowy kod wygenerowany i przekazany do Uploadera podczas sprawdzania pliku (jfxuOperation / checkFile),
- jfxuStatus - status występujący podczas transmisji pliku (jfxuOperation / dataFile) i może mieć postać: begin - pierwsza paczka, progress - kolejna paczka oraz end - ostatnia paczka;
- jfxuOffset - numer kolejny paczki występuje podczas transmisji pliku (jfxuOperation / dataFile),
- jfxuData - paczka (fragment pliku) zakodowany algorytmem Base64 z opcją URL_SAFE przeznaczona do zapisu,
- d_time - czas wysłania z Uploadera.
Logikę przechwytywania pliku można wywnioskować z powyższego kodu. Warto mieć na uwadze, żeby wygenerować odpowiedni unikatowy kod podczas sprawdzania pliku i przesłać go do Uploadera. Poszczególne paczki rozkodowywać Base64 i dopisywać do pliku. Autoryzacja może być zaszyta w sesji, w ciasteczkach lub w unikatowym kluczu. Odpowiedzi do Uploadera rozdzielać średnikiem: czy operacja zakończyła się sukcesem (true / false); wiadomość zwrotna (opis błędu lub w przypadku pozytywnego sprawdzenia pliku unikatowy klucz). Jeżeli ktoś ma problem ze zrozumieniem kodu lub opisu, a chciałby napisać skrypt np w PHP to zapraszam do zadawania pytań. Adres e-mail w zakładce KONTAKT.
Schemat komunikacji Klient - Serwer |