2009-07-10 13 views
44

Próbuję dowiedzieć się, jak przesłać jeden plik przy użyciu widgetu FileWpload GWTs. Używam GWT i Google AppEngine z Javą, ale chciałbym przesłać plik na mój własny serwer Linux. Mam następujący kod, ale teraz już nie mogę dowiedzieć się, jak przesłać swój plik do serwera Google AppServer i zapisać go na inny serwer:Przesyłanie pliku podstawowego w GWT

public class FileUploader{ 

    private ControlPanel cp; 
    private FormPanel form = new FormPanel(); 
    private FileUpload fu = new FileUpload(); 

    public FileUploader(ControlPanel cp) { 
     this.cp = cp; 
     this.cp.setPrimaryArea(getFileUploaderWidget()); 
    } 

    @SuppressWarnings("deprecation") 
    public Widget getFileUploaderWidget() { 
     form.setEncoding(FormPanel.ENCODING_MULTIPART); 
     form.setMethod(FormPanel.METHOD_POST); 
     // form.setAction(/* WHAT SHOULD I PUT HERE */); 

     VerticalPanel holder = new VerticalPanel(); 

     fu.setName("upload"); 
     holder.add(fu); 
     holder.add(new Button("Submit", new ClickHandler() { 
      public void onClick(ClickEvent event) { 
       GWT.log("You selected: " + fu.getFilename(), null); 
       form.submit(); 
      } 
     })); 

     form.addSubmitHandler(new FormPanel.SubmitHandler() { 
      public void onSubmit(SubmitEvent event) { 
       if (!"".equalsIgnoreCase(fu.getFilename())) { 
        GWT.log("UPLOADING FILE????", null); 
             // NOW WHAT???? 
       } 
       else{ 
        event.cancel(); // cancel the event 
       } 

      } 
     }); 

     form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() { 
      public void onSubmitComplete(SubmitCompleteEvent event) { 
       Window.alert(event.getResults()); 
      } 
     }); 

     form.add(holder); 

     return form; 
    } 
} 

Teraz, co muszę zrobić? Co trzeba zrobić, aby umieścić w web.xml i jak mogę napisać aplet, więc mogę zapisać plik i powrócić URL danego obiektu (jeśli to możliwe)

Odpowiedz

57

Oto kod z mojej aplikacji:

1) I Utworzono klasę akceptować żądania http:

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.apache.commons.fileupload.FileItemIterator; 
import org.apache.commons.fileupload.FileItemStream; 
import org.apache.commons.fileupload.servlet.ServletFileUpload; 

public class FileUpload extends HttpServlet{ 
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     ServletFileUpload upload = new ServletFileUpload(); 

     try{ 
      FileItemIterator iter = upload.getItemIterator(request); 

      while (iter.hasNext()) { 
       FileItemStream item = iter.next(); 

       String name = item.getFieldName(); 
       InputStream stream = item.openStream(); 


       // Process the input stream 
       ByteArrayOutputStream out = new ByteArrayOutputStream(); 
       int len; 
       byte[] buffer = new byte[8192]; 
       while ((len = stream.read(buffer, 0, buffer.length)) != -1) { 
        out.write(buffer, 0, len); 
       } 

       int maxFileSize = 10*(1024*1024); //10 megs max 
       if (out.size() > maxFileSize) { 
        throw new RuntimeException("File is > than " + maxFileSize); 
       } 
      } 
     } 
     catch(Exception e){ 
      throw new RuntimeException(e); 
     } 

    } 
} 

2) Następnie w moim web.xml dodałem te linie:

<servlet> 
    <servlet-name>fileUploaderServlet</servlet-name> 
    <servlet-class>com.testapp.server.FileUpload</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>fileUploaderServlet</servlet-name> 
    <url-pattern>/testapp/fileupload</url-pattern> 
</servlet-mapping> 

3) I form.action to zrobił:

form.setAction(GWT.getModuleBaseURL()+"fileupload"); 
+1

mam dokładny jak OP: Projekt jest hostowany na GAE i chcę przesłać plik na mój własny serwer internetowy Linux. OP wybrał odpowiedź jako najlepszą odpowiedź, więc myślę, że pomogło mu to w pytaniu, ale nie wiem, gdzie umieścić klasę FileUpload, czy jest ona w GAE wraz z innymi plikami projektu? A co z serwerem Linux? Jak otrzyma pliki? Gdzie jest określony adres? A nazwa pliku? Jestem zdezorientowany tym kawałkiem kodu. –

+3

Czy 10 MiB "10 * 1024 * 1024", a nie "10 * (1024 * 2)", czy też "megs" to alternatywna nazwa dla 2 KiB? –

+2

10 * (1024 * 2) to 20Kb, ale nie 10Mb – Antonio

5

W GWT, można zakładać plik na serwer przy użyciu metod formularza http, i należy użyć dostarczonego HttpServlet zaakceptować i zapisać dane jak blogi binarnych w AppEngine BigTable.

Następnie potrzebujesz drugiego HttpServlet do odczytania pliku z bigtable, SET THE MIME TYPE IN THE HTTP HEADER {i opcje buforowania}, a następnie przesyłaj plik do użytkownika.

Chociaż RPC nie jest koniecznie potrzebny, należy poinformować klienta, jaki jest wygenerowany identyfikator pliku, aby mógł uzyskać do niego dostęp (chyba, że ​​chcesz, aby użytkownik podał identyfikator i zmusił go do obawiania się nadpisań nazw .... ..ick}. Możesz użyć polecenia rpc, aby poprosić o listę pojedynczego identyfikatora {takiego jak "najnowszy identyfikator pliku przez użytkownika"} lub możesz zwrócić ten identyfikator w treści odpowiedzi serwera UploadServlet ... ale musisz się upewnić, że Twój cel jest to element iframe na stronie, aby upewnić się, że element iframe ma treść między zdarzeniem submit i faktyczną odpowiedzią serwera, a następnie przeanalizować i użyć tego identyfikatora w gwt, aby utworzyć znacznik img lub object, który używa tego pliku.

Kluczową częścią jest jeden serwlet do przesłania, a drugi do pobrania. Pamiętaj, że BigTable tylko przechowuje binarne obiekty blob, więc potrzebujesz również encji danych, aby mieć typ mime/treści, który można odczytać z pliku wejściowego {nigdy nie polegaj na rozszerzeniach plików!}. Ponadto istnieje 1 MB na jednostkę w BigTable i 10 MB na żądanie dla darmowych kont. Możesz chcieć, aby twoja encja danych zawierała listę 1-10 obiektów typu blob, z których każda ma maksymalnie 1024 bajty.

Zasadniczo najlepiej jest znaleźć działającą, darmową kopię, taką jak Google File Service, i rozszerzyć ją, aby dowiedzieć się, jak działa system.

Jeśli chcesz, będę publikować moją własną wersję open-source do obsługi plików, kiedy skończę widżety kontroli gwt i będę mógł uznać to wszystko za wystarczająco stabilne, aby być użyteczne dla każdego. Adres e-mail x AT aiyx DOT info, jeśli chcesz, żebym wysłał ci słoik z błędnym kodem.

11

Proponuję użyć numeru , ponieważ jest on prosty w użyciu i rozszerzony. Możesz dodać go do swojego projektu w czasie krótszym niż 10 minut i od razu obsługuje GAE (używając GWTUpload-GAE). Zobacz examples dla niektórych typowych scenariuszy użycia.

+2

Uwaga: GWTUpload wymaga sesji –

+1

Jakie są plusy/minusy używania GWTUpload przez rozwiązanie oferowane przez @KevMo – kroiz

+2

GWTUpload pozwala na asynchroniczne przesyłanie z aktualizacjami statusu, przesyłaniem wielu plików i wiele więcej. Wydaje się być pełnym zamiennikiem popularnych opcji Flash. – rluba

2

O ile nie korzystasz już z innych frameworków, zdecydowanie sugeruję użycie zwykłego waniliowego GWT i jego natywnych komponentów. Jeśli korzystasz z innych frameworków, możesz znacznie zwiększyć rozmiar aplikacji.

Korzystanie z rodzimych składników można zrobić w 3 krokach:

  1. Tworzenie wysyłania pliku aplet
  2. Modyfikuj web.xml
  3. Zrób GWT Prześlij formularz

Co ciekawe, część GWT jest najłatwiejsza. Możesz skopiować mój kod na GWT Upload in 3 easy steps, jeśli chcesz. Wesołe przesyłanie!

+0

Zasadniczo tak naprawdę nie widzę różnicy w stosunku do http://stackoverflow.com/a/1111606/787660, więc myślę, że odpowiedź jest w większości podobna, ale druga nie jest gdzieś połączona ... – Chris