类似GMail的文件上传进度条和GWT?

类似GMail的文件上传进度条和GWT?,gwt,Gwt,所有Gmail用户都应该已经注意到文件上传进度条最近已经更新 我想知道这样的效果是否可以用GWT实现。 我对GWT相当陌生,因此如果有任何GWT源代码可以帮助我测试该函数,那将非常有用 更新 最后我和斯弗普劳德一起去了。不过,这项质询下的其他建议都是有效的。只要尝试不同的选择,选择一个你喜欢的 检查一下,它有一个完全符合您需要的实现。如果您有一个java后端,您只需启动一个文件上传,然后在计时器上轮询服务器,查看它在哪里(比如说每隔一两秒钟)。java文件上载二进制文件(apache commo

所有Gmail用户都应该已经注意到文件上传进度条最近已经更新

我想知道这样的效果是否可以用GWT实现。 我对GWT相当陌生,因此如果有任何GWT源代码可以帮助我测试该函数,那将非常有用

更新

最后我和斯弗普劳德一起去了。不过,这项质询下的其他建议都是有效的。只要尝试不同的选择,选择一个你喜欢的

检查一下,它有一个完全符合您需要的实现。

如果您有一个java后端,您只需启动一个文件上传,然后在计时器上轮询服务器,查看它在哪里(比如说每隔一两秒钟)。java文件上载二进制文件(apache commons二进制文件)支持告诉您当前的进度,因此这很简单。

使用SWFUpload via


与其他方法相比,它的主要优点是不需要任何特殊的服务器代码。您甚至可以上传到另一个域(如果有一个crossdomain.xml允许的话)。

您可以使用GwtSwfExt,它是SWFUpload(与SWFUpload gwt lib相同)之上的包装器,您可以从中下载示例和源代码。

在创建您自己的文件上传进度时,而不是在一个小的设定时间从服务器上拉它,您可以让客户端在2秒钟内显示一个不确定条,让服务器计算更改的估计完成时间,改为每5、10秒提取一次新的估计值。这应该对流量几乎没有影响。

请查看此库:。它非常容易使用,在我检查过的所有浏览器和操作系统中都能正常工作。它使用ajax请求来计算进度。顺便说一句,Swfupload在linux和Mac上做得不好。

最近我启动了一个自己的项目,名为
gwtupld

主要目标是为尖端浏览器提供最佳的文件上传体验 对其他所有人来说都是可接受的可用性。目前,有以下主要特点

  • 多文件选择
  • 拖放
  • 进度条
  • 外观光鲜朴素
  • 所有浏览器的一致行为
  • 易于视觉定制
  • 没有外部依赖项,只有GWT
请随意提出并提交错误/功能建议。 您可以签出源代码,然后键入

gradlew gwtcompile devmode
并得到它将开始一个完整的功能
沙盒(真正保存文件的服务器端应该可以使用)

我以前使用过这个工具:

与这里的其他建议不同,它不仅提供了适当的API来显示上载进度,还提供了通过选择多个文件进行批量上载的能力,并且还提供了拖放支持。它还具有HTML5之前的回退机制

我在这方面运气很好。最近它在Firefox 7和Firefox 8中出现了漏洞,我不得不将此补丁应用到它上,但除此之外,它的效果非常好:

@@ -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
我还必须添加以下行-这些行描述了回退机制是如何工作的。如果您希望您的代码在HTML5缺失的情况下依赖于下面所示的SWFUploader实现,您可以做类似的事情

    <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>
以下是该接口的gwt fileapi实现:

package com.hierarchycm.gxt.client.fileUpload;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.gwtpro.html5.fileapi.client.FileApiSupport;
import com.gwtpro.html5.fileapi.client.drop.DropHandler;
import com.gwtpro.html5.fileapi.client.file.File;
import com.gwtpro.html5.fileapi.client.file.FileEvent;
import com.gwtpro.html5.fileapi.client.file.FileEvent.FileEventHandler;
import com.gwtpro.html5.fileapi.client.ui.FileInput;
import com.gwtpro.html5.fileapi.client.upload.UploadRequest;
import com.gwtpro.html5.fileapi.client.upload.UploadRequestBuilder;
import com.gwtpro.html5.fileapi.client.upload.UploadRequestCallback;

public class FileUploadHtmlImpl extends FileInput implements FileUpload {

    private Grid uploadTable;   
    int currentFile =0;
    String url;
    File[] files;   
    UploadRequestBuilder fileUploader;
    Uploader uploader;

    public FileUploadHtmlImpl() {

    }

    FileUploadHtmlImpl(Grid updateTable, Uploader uploader, String url) {
        this(updateTable, uploader, url, true);
    }

    FileUploadHtmlImpl(Grid updateTable, Uploader uploader, String url, boolean createDropHandler) {
        initialize(updateTable, uploader, url, createDropHandler);
        //this.setCallback(getMyCallback());
    }

    public void initialize(Grid updateTable, Uploader uploader, String url, boolean createDropHandler){
        this.url = url;
        this.uploadTable = updateTable;
        this.uploader = uploader;
        this.setAllowMultipleFiles(true);
        this.addChangeHandler(new ChangeHandler() {
                @Override
                public void onChange(ChangeEvent event) {
                    addFiles(FileUploadHtmlImpl.this.getFiles());   
                    uploadFiles();
                }
          });

        if (createDropHandler) {
            createDropHandler();
        }
    }

     private File[] jsArrToArr (JsArray<File> ipFiles) { 

         File [] result = new File [ipFiles.length()];       
         for (int i = 0; i < ipFiles.length(); ++i) {
             result[i] = ipFiles.get(i);
         }
         return result;
     }

    private UploadRequestCallback getMyCallback() {
        return new UploadRequestCallback() {

            @Override
            public void onError(UploadRequest request, Throwable exception) {
                uploadTable.setText(currentFile + 1, 2, "failed: " + exception.getMessage());
                uploadNextFile(currentFile + 1);
            }

            @Override
            public void onResponseReceived(UploadRequest request, Response response) {
                uploadTable.setText(currentFile + 1, 2, "success: " + response.getText());
                uploadNextFile(currentFile + 1);

                //If we just finished uploading  do your thing
                if (currentFile == files.length) {
                    setDisabled(false);
                    uploader.uploadDoneEventHandler();
                }
            }

            @Override
            public void onUploadProgress(UploadRequest request, int bytesUploaded) {
                uploadTable.setText(currentFile + 1, 2, bytesUploaded + "");
            }
        };
    }

    public void createDropHandler() {
          RootPanel rootPanel = RootPanel.get();
          DropHandler dropHandler = new DropHandler(rootPanel);
            this.fileUploader = new UploadRequestBuilder(url);
            this.fileUploader.setCallback(getMyCallback());
            dropHandler.addFileEventHandler(new FileEventHandler() {

                @Override
                public void onFiles(FileEvent event) {
                    addFiles(jsArrToArr(event.getFiles()));
                    uploadFiles();
                }
            });
    }

     private void addFiles (File[] ipFiles) {
            files = ipFiles;
            uploadTable.clear();
            uploadTable.resize(files.length + 1, 3);
            uploadTable.setText(0, 0, "File name");
            uploadTable.setText(0, 1, "File size");
            uploadTable.setText(0, 2, "Progress");
            for (int i = 0; i < files.length; ++i) {                
                uploadTable.setText(i + 1, 0, files[i].getFileName());                          
                uploadTable.setText(i + 1, 1, files[i].getFileSize() + "");
                uploadTable.setText(i + 1, 2, "");
            }
    }

    public void uploadNextFile(int index) {
            for (String paramName : uploader.getPostParams().keySet()) {
                fileUploader.setHeader(paramName, uploader.getPostParams().get(paramName));                                     
            }

            currentFile = index;
            this.setDisabled(true);
            if (index < this.files.length) {
                try {
                    this.fileUploader.setHeader("itemName", files[currentFile].getFileName());
                    this.fileUploader.sendFile(files[currentFile]);
                } catch (RequestException e) {
                    this.uploadTable.setText(index + 1, 2, "failed: " + e.getMessage());
                    uploadNextFile(index + 1);
                }
            }


     }

    public void uploadFiles() {
        uploadNextFile(0);
    }

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

    @Override
    public void readyToPaint() {
        //no need to do anything - already painted for non swf
    }

    @Override
    public void reset() {
        // TODO Auto-generated method stub

    }

    private void showCapabilities() {
        RootPanel
                .get("status")
                .getElement()
                .setInnerHTML(
                        "Drag and Drop Support: "
                                + (FileApiSupport.isDragDropSupported() ? "Yes"
                                        : "No")
                                + "<br/>HTTPXmlRequest Level 2: "
                                + (FileApiSupport.isHttpXmlRequestLevel2() ? "Yes"
                                        : "No")
                                + "<br/>File input supports multiple files: "
                                + (FileApiSupport
                                        .isMultipleFileInputSupported() ? "Yes"
                                        : "No")+"<br/><br/>");
    }

}
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();

    }
}
package com.hierarchycm.gxt.client.fileUpload;
导入com.google.gwt.core.client.JsArray;
导入com.google.gwt.event.dom.client.ChangeEvent;
导入com.google.gwt.event.dom.client.ChangeHandler;
导入com.google.gwt.http.client.RequestException;
导入com.google.gwt.http.client.Response;
导入com.google.gwt.user.client.Window;
导入com.google.gwt.user.client.ui.Grid;
导入com.google.gwt.user.client.ui.RootPanel;
导入com.google.gwt.user.client.ui.Widget;
导入com.gwtpro.html5.fileapi.client.fileapi支持;
导入com.gwtpro.html5.fileapi.client.drop.DropHandler;
导入com.gwtpro.html5.fileapi.client.file.file;
导入com.gwtpro.html5.fileapi.client.file.FileEvent;
导入com.gwtpro.html5.fileapi.client.file.FileEvent.FileEventHandler;
导入com.gwtpro.html5.fileapi.client.ui.FileInput;
导入com.gwtpro.html5.fileapi.client.upload.UploadRequest;
导入com.gwtpro.html5.fileapi.client.upload.UploadRequestBuilder;
导入com.gwtpro.html5.fileapi.client.upload.UploadRequestCallback;
公共类FileUploadHtmlImpl扩展FileInput实现FileUpload{
私有网格上传表;
int currentFile=0;
字符串url;
文件[]文件;
UploadRequestBuilder文件上传器;
上传器上传器;
公共文件上传HTMLimpl(){
}
FileUploadHtmlImpl(网格更新表、上传器上传器、字符串url){
这(updateTable、uploader、url、true);
}
FileUploadHtmlImpl(网格更新表、上传器上传器、字符串url、布尔createDropHandler){
初始化(updateTable、uploader、url、createDropHandler);
//this.setCallback(getMyCallback());
}
public void initialize(网格updateTable、上载器上载器、字符串url、布尔createDropHandler){
this.url=url;
this.uploadTable=updateTable;
this.uploader=上传器;
此.setAllowMultipleFiles(true);
this.addChangeHandler(新的ChangeHandler(){
@凌驾
更改后的公共作废(更改事件){
addFiles(FileUploadHtmlImpl.this.getFiles());
上传文件();
}
});
如果(createDropHandler){
createDropHandler();
}
}
私有文件[]jsArrToArr(JsArray ipFiles){
File[]result=新文件[ipFiles.length()];
对于(int i=0;ipackage 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();

    }
}
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;
    }
}