2009-03-09 14 views
26

Tutti gli utenti Gmail dovrebbero aver già notato che la barra di avanzamento del caricamento del file è stata aggiornata di recente.GMail come barra di avanzamento caricamento file con GWT?

Mi chiedo se sia possibile implementare questo effetto con GWT. Sono abbastanza nuovo con GWT, quindi se qualche codice sorgente GWT che può aiutarmi a testare la funzione sarebbe molto utile.

Aggiornamento
Ho finito per andare con SWFUpload. Tuttavia, altri suggerimenti sotto questa domanda sono tutti validi. Prova semplicemente diverse opzioni e scegli quello che ti piace!

risposta

21

Dai un'occhiata a questa biblioteca: http://code.google.com/p/gwtupload/. È davvero facile da usare e funziona perfettamente con tutti i browser e il sistema operativo che ho controllato. Usa le richieste ajax per calcolare i progressi. BTW Swfupload non funziona bene su Linux e Mac.

+0

sì, questo è quello che ho finito per usare alla fine. È molto facile da installare e integrare. – codingbear

+1

La barra di avanzamento non funziona con GAE (vedi http://code.google.com/p/gwtupload/issues/detail?id=111) –

+0

gwtupload è stato corretto per GAE http://code.google.com/p/gwtupload/source/dettaglio? r = 926 – Ena

3

Verificare GWTC Upload, che ha un'implementazione esattamente ciò che stai cercando.

+0

non vedo nulla di utile lì. Di solito, c'è un codice sorgente disponibile per il download o la visualizzazione. – codingbear

+0

Fare clic sulla scheda sorgente: # I non membri possono estrarre una copia di lavoro di sola lettura anonimamente su HTTP. svn checkout http://gwtcupload.googlecode.com/svn/trunk/ gwtcupload-read-only – rustyshelf

3

È semplice scrivere il proprio se si dispone di un back-end Java, è sufficiente avviare un caricamento di file e quindi eseguire il polling del server su un timer per vedere dove si trova (ad esempio ogni due o due). I binari di upload del file java (quelli di apache commons) supportano il progresso corrente, quindi è banale da fare.

+0

Hm, ho pensato che potrebbe essere più elegante perché il polling del server ogni secondo è troppo fastidioso, specialmente le app web che hanno il collo di bottiglia della rete il tempo. (forse non vedo da quello che stai cercando di dire?) – codingbear

+0

una tecnica di non-polling è quella di utilizzare un flash uploader. Ecco come getdropbox.com fa il loro caricamento: sembra fantastico e puoi caricare file in parallelo, credo. Dategli un'occhiata su www.getdropbox.com – Chii

+0

@ Chii, ecco cosa ho capito. Penso che Gmail utilizzi anche Flash Uploader, perché hanno incorporato il file SWF. Sai come farlo in flash e integrarlo con una tipica app web? (Conosco già Dropbox: D) – codingbear

4

Usa SWFUpload via swfupload-gwt

Il vantaggio principale rispetto agli altri metodi è questo non richiede alcun codice server speciale. Potresti anche caricare su un altro dominio (se esiste un crossdomain.xml che lo consente).

+0

Inoltre ... questa è (si spera) una soluzione a breve termine, non appena mi auguro che le funzionalità fornite da Gears saranno disponibili in modo nativo nei browser. http://code.google.com/apis/gears/api_httprequest.html#HttpRequestUpload –

0

È possibile utilizzare GwtSwfExt che è wrapper su SWFUpload (lo stesso di Swfupload-gwt lib) è possibile scaricare esempio e codice sorgente da http://code.google.com/p/gwtswfext.

0

Quando si crea il proprio avanzamento del caricamento del file, invece di estrarlo dal server del modulo in un tempo limitato, è possibile fare in modo che il client visualizzi una barra indeterminata per 2 secondi e richiedere al server di calcolare il tempo stimato di fine determinato e tirare nuove stime ogni 5, 10 secondi invece. che dovrebbe avere poco o nessun effetto sul traffico.

1

Recentemente ho iniziato un progetto della mia chiamata gwtupld

http://github.com/kompot/gwtupld/

L'obiettivo principale è quello di fornire la migliore esperienza di upload di file per il taglio di browser all'avanguardia e usabilità accettabile per tutti gli altri. In questo momento, seguenti caratteristiche chiave sono presenti

  • selezione multipla di file
  • drag'n'drop
  • barre di avanzamento
  • slick e semplice esterno
  • comportamento coerente per tutti i browser
  • facilità di personalizzazione visiva
  • nessuna dipendenza esterna ma GWT

Sentitevi liberi di presentare una segnalazione di bug/funzionalità. È possibile controllare il codice sorgente, quindi digitare

gradlew gwtcompile devmode 

e farlo inizierà una completamente funzionale sandbox (lato server con il salvataggio dei file vero e proprio dovrebbe funzionare)

6

Ho usato questo strumento prima:

http://code.google.com/p/gwt-fileapi/

a differenza degli altri suggerimenti qui, non solo si dà l'API appropriata per mostrare avanzamento del caricamento, ma dà anche la possibilità di fare upload in batch selezionando m file multipli e fornisce anche il supporto per il trascinamento della selezione. Ha anche un meccanismo di fallback pre HTML5.

Ho avuto molta fortuna con esso gwt-fileap. Recentemente si è rotto in Firefox 7 e 8 e ho dovuto applicare questa patch ad esso - ma per il resto funziona davvero grande:

@@ -57,26 +57,33 @@ 

    /** 
     * gets the filename 
-  * 
+  * 
     * @return the filename 
     */ 
    public final native String getFileName() /*-{ 
-  return this.fileName; 
+  if(this.name) 
+     return this.name; 
+   else 
+     return this.fileName; 
+ 
    }-*/; 

    /** 
     * gets the file size in bytes 
-  * 
+  * 
     * @return the file size in bytes 
     */ 
    public final native int getFileSize() /*-{ 
-  return this.fileSize; 
+  if(this.size) 
+     return this.size; 
+   else 
+     return this.fileSize; 
    }-*/; 

    /** 
     * gets the MIME type of the file, may be null if the browser cannot detect 
     * the type 

ho dovuto anche aggiungere le seguenti linee al http://code.google.com/p/gwt-fileapi/source/browse/trunk/gwt-fileapi/src/com/gwtpro/html5/fileapi/Html5FileApi.gwt.xml - queste linee descrivono come il meccanismo di fallback lavori. Puoi fare qualcosa di simile se vuoi che il tuo codice ricada sull'implementazione di SWFUploader mostrata sotto nel caso in cui manchi HTML5.

<define-property name="fileapi.support" values="yes,no" /> 

    <property-provider name="fileapi.support"><![CDATA[ 
        var input=document.createElement('input'); 
        input.setAttribute('type','file'); 
        return input.files==null?'no':'yes'; 
    ]]></property-provider> 


    <replace-with 
      class="com.gwtpro.html5.fileapi.client.ui.FileInput.FileInputImplHtml5"> 
      <when-type-is 
        class="com.gwtpro.html5.fileapi.client.ui.FileInput.FileInputImpl" /> 
      <when-property-is name="fileapi.support" value="yes" /> 
      <any> 
        <when-property-is name="user.agent" value="ie8" /> 
        <when-property-is name="user.agent" value="safari" /> 
        <when-property-is name="user.agent" value="gecko1_8" /> 
        <when-property-is name="user.agent" value="opera" /> 
        <when-property-is name="user.agent" value="chrome" /> 
      </any> 
    </replace-with> 

Questo è come io lo uso nella mia domanda:

Questa è l'interfaccia che descrive l'astrazione:

public interface FileUpload { 
    public void uploadFiles(); 
    public Widget getWidget(); 
    public void initialize(Grid updateTable, Uploader uploader, String url, boolean createDropHandler); 
    public void setDisabled(boolean b); 
    public void readyToPaint(); 
    public void reset(); 

} 

Quello che segue è l'attuazione GWT-FileAPI dell'interfaccia:

Questa è l'implementazione di SWFUpload http://code.google.com/p/swfupload-gwt/ dello stesso Interfaccia:

package com.hierarchycm.gxt.client.fileUpload; 

import com.extjs.gxt.ui.client.widget.Html; 
import com.google.gwt.user.client.ui.Grid; 
import com.google.gwt.user.client.ui.Widget; 

public class FileUploadSwfImpl extends Html implements FileUpload { 

    SwfUploadUtil swfUploadUtil = null; 
    private Uploader uploader; 
    private String url; 
    private boolean createDropHandler; 
    private Grid updateTable; 



    static int uploadId = 0; 
    static String divTagId; 

    public FileUploadSwfImpl() { 
     divTagId = "swfupload" + uploadId++; 
     String divTag = "<div id=\"" + divTagId + "\"></div"; 
     this.setHtml(divTag); 
    } 

    @Override 
    public void uploadFiles() { 
     swfUploadUtil.startUpload();   
    } 

    @Override 
    public Widget getWidget() {  
     return this; 
    } 

    public void readyToPaint() {  

     swfUploadUtil = new SwfUploadUtil(uploader, updateTable, divTagId, url);  
    } 

    @Override 
    public void initialize(Grid updateTable, Uploader uploader, String url, boolean createDropHandler) { 

     this.uploader = uploader; 
     this.url = url; 
     this.createDropHandler = createDropHandler; 
     this.updateTable = updateTable; 

    } 

    @Override 
    public void setDisabled(boolean b) { 

     swfUploadUtil.setDisabled(b); 
     this.disabled = true; 

    } 

    @Override 
    public void reset() { 
     swfUploadUtil.reset(); 

    } 
} 

E questo è l'utilità della FileUploadSwfImpl dipende da:

package com.hierarchycm.gxt.client.fileUpload; 

import java.util.HashMap; 

import org.swfupload.client.File; 
import org.swfupload.client.SWFUpload; 
import org.swfupload.client.UploadBuilder; 
import org.swfupload.client.SWFUpload.ButtonAction; 
import org.swfupload.client.SWFUpload.ButtonCursor; 
import org.swfupload.client.event.DialogStartHandler; 
import org.swfupload.client.event.FileDialogCompleteHandler; 
import org.swfupload.client.event.FileQueuedHandler; 
import org.swfupload.client.event.UploadCompleteHandler; 
import org.swfupload.client.event.UploadErrorHandler; 
import org.swfupload.client.event.UploadProgressHandler; 
import org.swfupload.client.event.UploadSuccessHandler; 
import org.swfupload.client.event.FileDialogCompleteHandler.FileDialogCompleteEvent; 
import org.swfupload.client.event.FileQueuedHandler.FileQueuedEvent; 
import org.swfupload.client.event.UploadCompleteHandler.UploadCompleteEvent; 
import org.swfupload.client.event.UploadErrorHandler.UploadErrorEvent; 
import org.swfupload.client.event.UploadProgressHandler.UploadProgressEvent; 
import org.swfupload.client.event.UploadSuccessHandler.UploadSuccessEvent; 

import com.extjs.gxt.ui.client.widget.form.TextArea; 
import com.google.gwt.core.client.GWT; 
import com.google.gwt.user.client.Window; 
import com.google.gwt.user.client.ui.Grid; 

public class SwfUploadUtil { 

    HashMap<String, Integer> filenameRowHm = new HashMap<String, Integer>(); 

    private boolean resetIssued; 

    SWFUpload swfUpload = null; 
    private HashMap <String, File> files = new HashMap<String, File>();  
    int tableRow = 5; 
    Uploader uploader = null; 
    private Grid updateTable; 
    private String divName; 
    private String url; 

    synchronized private void removeFile(String id) { 
     files.remove(id); 
    }  

    public SwfUploadUtil(Uploader uploader, Grid updateTable, String divName, String url){ 
     reset(); 
     this.uploader = uploader; 
     this.updateTable = updateTable; 
     this.divName = divName; 
     this.url = url; 

     this.swfUpload = loadSWFUpload(); 
     updateTable.resize(5, 5); 
     updateTable.setText(2, 0, "Upload URL:"); 
     updateTable.setText(2, 1, url);   
     updateTable.setText(4, 0, "File Name"); 
     updateTable.setText(4, 1, "Bytes In"); 
     updateTable.setText(4, 2, "Status"); 
     updateTable.setText(4, 3, "File Size"); 
     updateTable.setText(4, 4, "Server response"); 

    } 


    public SWFUpload loadSWFUpload() { 

     this.updateTable = updateTable; 

     if (swfUpload == null) {   
      final UploadBuilder builder1 = new UploadBuilder(); 
      builder1.setHTTPSuccessCodes(200, 201); 
      builder1.setFileTypes("*.webm;*.asf;*.wma;*.wmv;*.avi;*.flv;*.swf;*.mpg;*.mpeg;*.mp4;*.mov;*.m4v;*.aac;*.mp3;*.wav;*.png;*.jpg;*.jpeg;*.gif"); 
      builder1.setFileTypesDescription("Images, Video & Sound"); 

      builder1.setButtonPlaceholderID(divName); 
      builder1.setButtonImageURL("./images/XPButtonUploadText_61x22.png"); 
      builder1.setButtonCursor(ButtonCursor.HAND); 
      builder1.setButtonWidth(61); 
      builder1.setButtonHeight(22); 
      builder1.setButtonAction(ButtonAction.SELECT_FILES); 

      builder1.setUploadProgressHandler(new UploadProgressHandler() { 

       public void onUploadProgress(UploadProgressEvent e) { 

        File f = e.getFile();     
        updateTable.setText(getFilenameRow(f), 2, String.valueOf(e.getBytesComplete())); 

       } 
      }); 

      builder1.setUploadSuccessHandler(new UploadSuccessHandler() { 
       public void onUploadSuccess(UploadSuccessEvent e) { 
        File f = e.getFile(); 
        updateTable.setText(getFilenameRow(f), 4, e.getServerData()); 
       } 
      }); 

      builder1.setUploadErrorHandler(new UploadErrorHandler() { 
       public void onUploadError(UploadErrorEvent e) { 
        File ff = e.getFile(); 
        String message = e.getMessage(); 
        if (message == null || message.trim().length() == 0) { 
         message = "upload failed"; 
        }    
        updateTable.setText(getFilenameRow(ff), 2, String.valueOf(message)); 

        removeFile(ff.getId()); 
        if (files.values().size() > 0) { 
         ff = files.values().iterator().next(); 
         updateTable.setText(getFilenameRow(ff), 2, "Started"); 
         swfUpload.startUpload(ff.getId());      
        } 
       } 
      }); 

      builder1.setUploadURL(url); 

      builder1.setDialogStartHandler(new DialogStartHandler() { 
       @Override 
       public void onDialogStart() { 
        if(resetIssued == true) { 
         filenameRowHm.clear(); 
         resetIssued = false; 
        }    
       }     
      } 
      ); 

      builder1.setUploadCompleteHandler(new UploadCompleteHandler() { 
       public void onUploadComplete(UploadCompleteEvent e) { 
        File f = e.getFile(); 

        updateTable.setText(getFilenameRow(f), 2, "Done"); 

        removeFile(f.getId()); 
        if (files.values().size() > 0) { 
         File ff = files.values().iterator().next(); 

         updateTable.setText(getFilenameRow(ff), 2, "Started"); 
         swfUpload.startUpload(ff.getId()); 
        } else {      
         uploader.uploadDoneEventHandler(); 
        } 
       } 
      }); 

      builder1.setFileQueuedHandler(new FileQueuedHandler() { 
       public void onFileQueued(FileQueuedEvent event) { 

        File f = event.getFile();     
        updateTable.setText(getFilenameRow(f), 2, "Queued");      
        files.put(f.getId(), f); 
       } 
      }); 

      builder1.setFileDialogCompleteHandler(new FileDialogCompleteHandler() { 
       public void onFileDialogComplete(FileDialogCompleteEvent e) {             



        updateTable.setText(2, 0, "Number of files"); 
        updateTable.setText(2, 1, String.valueOf(files.values().size())); 

        for(File f : files.values()) { 
         getFilenameRow(f); 
        } 

        if (files.values().size() > 0) { 

         for (String paramName : uploader.getPostParams().keySet()) { 
          swfUpload.addPostParam(paramName,uploader.getPostParams().get(paramName));       
         } 
        } 
       } 
      }); 
      swfUpload = builder1.build(); 

     } 

     return swfUpload; 

    } 

    public int getFilenameRow (File f) { 
     Integer filenamerow = filenameRowHm.get(f.getId()); 

     if (filenamerow == null) { 
      updateTable.resize(tableRow+1, 5); 
      filenamerow = new Integer(tableRow++); 
      updateTable.setText(filenamerow.intValue(), 0, f.getName()); 
      updateTable.setText(filenamerow.intValue(), 3, String.valueOf(f.getSize())); 
      //updateTable.setText(filenamerow.intValue(), 3, String.valueOf(f)); 
      filenameRowHm.put(f.getId(), filenamerow); 
     } 

     return filenamerow.intValue(); 
    } 

    public void startUpload() { 
     uploader.uploadStartedEventHandler(); 
     swfUpload.startUpload(); 
    } 

    public void setDisabled(boolean disabled) { 
     swfUpload.setButtonDisabled(disabled); 


    } 

    public void reset() { 
     // TODO Auto-generated method stub 
     resetIssued = true; 
    } 
} 
Problemi correlati