2009-03-09 29 views
26

Tất cả người dùng Gmail nên đã nhận thấy rằng thanh tiến trình tải lên tệp đã được cập nhật gần đây.GMail như thanh tiến trình tải tệp lên với GWT?

Tôi tự hỏi rằng hiệu ứng này có thể thực hiện với GWT. Tôi khá mới với GWT, vì vậy nếu bất kỳ mã nguồn GWT nào có thể giúp tôi kiểm tra chức năng sẽ rất hữu ích.

Cập nhật
Tôi đã kết thúc bằng SWFUpload. Tuy nhiên, các đề xuất khác theo câu hỏi này đều hợp lệ. Chỉ cần thử các tùy chọn khác nhau và chọn tùy chọn bạn thích!

Trả lời

21

Hãy xem thư viện này: http://code.google.com/p/gwtupload/. Nó thực sự dễ sử dụng và hoạt động tốt trong tất cả các trình duyệt và hệ điều hành mà tôi đã kiểm tra. Nó sử dụng các yêu cầu ajax để tính toán tiến độ. BTW Swfupload không hoạt động tốt trong Linux và Mac.

+0

có, đây là những gì tôi đã sử dụng cuối cùng. Nó rất dễ cài đặt và tích hợp. – codingbear

+1

Thanh tiến trình sẽ không hoạt động với GAE (xem http://code.google.com/p/gwtupload/issues/detail?id=111) –

+0

gwtupload đã được sửa cho GAE http://code.google.com/p/gwtupload/source/detail? r = 926 – Ena

3

Kiểm tra GWTC Upload, trong đó có triển khai chính xác những gì bạn đang tìm kiếm.

+0

tôi không thấy bất cứ điều gì hữu ích ở đó. Thông thường, có sẵn mã nguồn để tải xuống hoặc xem. – codingbear

+0

Nhấp vào tab nguồn: # Không phải thành viên có thể kiểm tra một bản sao làm việc chỉ đọc ẩn danh qua HTTP. svn checkout http://gwtcupload.googlecode.com/svn/trunk/ gwtcupload-read-only – rustyshelf

3

Nó không đáng kể nếu bạn có một kết thúc java, bạn chỉ cần bắt đầu tải lên tệp và sau đó thăm dò ý kiến ​​máy chủ trên bộ đếm thời gian để xem vị trí của nó (cứ sau một hoặc hai giây). Các tập tin tải lên tập tin nhị phân java (apache commons những người thân) hỗ trợ cho bạn biết tiến độ hiện tại vì vậy nó tầm thường để làm.

+0

Hm, tôi nghĩ rằng nó có thể thanh lịch hơn bởi vì bỏ phiếu máy chủ mỗi giây là quá phiền hà, đặc biệt là các ứng dụng web có tắc nghẽn mạng tất cả thời gian. (có lẽ tôi không nhìn thấy từ những gì bạn đang cố gắng nói?) – codingbear

+0

một kỹ thuật không bỏ phiếu là sử dụng trình tải lên flash. Đây là cách getdropbox.com thực hiện việc tải lên của họ - có vẻ tuyệt vời và bạn có thể tải lên các tệp song song mà tôi tin. Hãy xem tại www.getdropbox.com – Chii

+0

@Chii, đó là những gì tôi đã tìm ra. Tôi nghĩ Gmail cũng sử dụng trình tải lên flash vì chúng nhúng tệp swf. Bạn có biết làm thế nào để làm điều đó trong flash và tích hợp với một ứng dụng web điển hình? (Tôi đã biết Dropbox: D) – codingbear

4

Sử dụng SWFUpload qua swfupload-gwt

Ưu điểm chính so với các phương pháp khác là điều này không đòi hỏi bất kỳ mã máy chủ đặc biệt. Bạn thậm chí có thể tải lên một tên miền khác (nếu có một crossdomain.xml cho phép nó).

+0

Ngoài ra ... đây là (hy vọng) một giải pháp ngắn hạn, ngay sau đó tôi hy vọng rằng các tính năng được cung cấp bởi Gears sẽ có sẵn tự nhiên trong các trình duyệt. http://code.google.com/apis/gears/api_httprequest.html#HttpRequestUpload –

0

Bạn có thể sử dụng GwtSwfExt là trình bao bọc trên đầu trang của SWFUpload (Giống như Swfupload-gwt lib), bạn có thể tải xuống ví dụ và mã nguồn từ http://code.google.com/p/gwtswfext.

0

Khi tạo tiến trình tải lên tệp của riêng bạn, thay vì kéo nó thành máy chủ trong một thời gian đặt nhỏ, bạn có thể yêu cầu khách hàng hiển thị thanh không xác định trong 2 giây và yêu cầu máy tính tính toán thời gian kết thúc ước tính xác định và kéo các ước tính mới cứ sau 5, 10 giây để thay thế. nên có ít hoặc không ảnh hưởng đến lưu lượng truy cập.

1

Gần đây tôi bắt đầu một dự án của riêng tôi gọi gwtupld

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

Mục đích chính là cung cấp tập tin tải lên kinh nghiệm tốt nhất để cắt các trình duyệt cạnh và khả năng sử dụng chấp nhận được đối với tất cả những người khác. Bởi thời điểm này, các tính năng chính sau đây có mặt

  • lựa chọn nhiều tập tin
  • drag'n'drop
  • thanh tiến
  • trơn và ngoại thất đơn giản
  • hành vi phù hợp cho tất cả các trình duyệt
  • dễ dàng tùy chỉnh trực quan
  • không có phụ thuộc bên ngoài nhưng GWT

Hãy thoải mái ngã ba và gửi lỗi/đề xuất tính năng. Bạn có thể kiểm tra mã nguồn, sau đó gõ

gradlew gwtcompile devmode 

và nhận được nó sẽ bắt đầu một đầy đủ chức năng sandbox (phía máy chủ với lưu file thực nên làm việc)

6

Tôi đã sử dụng công cụ này trước:

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

không giống như những gợi ý khác ở đây, không chỉ có khả năng cung cấp cho các API thích hợp để hiển thị tiến trình tải lên, nó cũng cung cấp cho khả năng làm cập nhật hàng loạt bằng cách chọn m các tệp ultiple và nó cũng hỗ trợ kéo và thả. Nó cũng có cơ chế dự phòng HTML5 trước.

Tôi đã có may mắn với nó gwt-fileap. Gần đây nó đã phá vỡ trong Firefox 7 và 8 và tôi đã phải áp dụng bản vá này để nó - nhưng mặt khác nó hoạt động thực sự tuyệt vời:

@@ -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 

Tôi cũng đã có thêm những dòng sau vào http://code.google.com/p/gwt-fileapi/source/browse/trunk/gwt-fileapi/src/com/gwtpro/html5/fileapi/Html5FileApi.gwt.xml - những dòng mô tả cách cơ chế dự phòng công trinh. Bạn có thể làm điều gì đó tương tự nếu bạn muốn mã của mình quay lại triển khai SWFUploader được hiển thị bên dưới trong trường hợp HTML5 bị thiếu.

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

Đây là cách tôi sử dụng nó trong ứng dụng của tôi:

Đây là giao diện mô tả trừu tượng:

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

} 

Sau đây là việc thực hiện gwt-FileAPI của giao diện:

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/>"); 
    } 

} 

Đây là triển khai SWFUpload http://code.google.com/p/swfupload-gwt/ giống nhau Giao diện:

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

    } 
} 

Và đây là tiện ích các FileUploadSwfImpl phụ thuộc vào:

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; 
    } 
} 
Các vấn đề liên quan