【问题标题】:How to upload file on GAE with GWT?如何使用 GWT 在 GAE 上上传文件?
【发布时间】:2012-04-06 10:21:03
【问题描述】:

我已经尝试了几个小时,所以也许换一双眼睛会有所帮助。

我正在尝试使用 Google App Engine 上的 GWT(使用 UiBinder)将文件上传到服务器。按照我能找到的所有示例,看起来它们应该可以工作,但服务器的“发布”方法显示上传了 0 个项目。

这是客户端代码:

FormUploader.ui.xml:

<g:FormPanel action="/formImageUploader" ui:field="formPanel">
    <g:VerticalPanel>
      <g:FileUpload ui:field="uploader"></g:FileUpload>
      <g:Button ui:field="submit">Submit</g:Button>
    </g:VerticalPanel>
</g:FormPanel>

FormUploader.java:

 @UiField
  FormPanel formPanel;

  @UiField
  FileUpload uploader;

  @UiField
  Button submit;

 public FormUploader() {
    initWidget(uiBinder.createAndBindUi(this));

    formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
    formPanel.setMethod(FormPanel.METHOD_POST);
    addSubmitHandlers();
  }

  private void addSubmitHandlers() {    
    formPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
      @Override
      public void onSubmitComplete(SubmitCompleteEvent event) {
        Core.log("Inside submitComplete");
        Window.alert(event.getResults());
      }
    });
  }

web.xml:

  <servlet>
    <servlet-name>formImageUploader</servlet-name>
    <servlet-class>com.company.server.FormImageUploader</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>formImageUploader</servlet-name>
    <url-pattern>/formImageUploader</url-pattern>
  </servlet-mapping>

FormImageUploader.java:

public class FormImageUploader extends HttpServlet {

  protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
    log.info("Request.getContentLength(): " + request.getContentLength());
    log.info("Content type: " + request.getContentType());

    log.info("Parm names: ");
    for (Object paramName : request.getParameterMap().keySet()) {
      log.info("__Param name: " + paramName.toString());
    }
    log.info("Attribtue names: ");
    Enumeration enu = request.getAttributeNames();
    while (enu.hasMoreElements()) {
      log.info("__Attribute name: " + enu.nextElement().toString());
    }
    log.info("Header names: ");
    enu = request.getHeaderNames();
    while (enu.hasMoreElements()) {
      log.info("__Header name: " + enu.nextElement().toString());
    }
    resp.getWriter().println("Post Code has finished executing"); 
}

这一切执行得很好,客户端显示一个包含邮政编码已完成执行的警告框,但我不知道如何获取我要上传的文件的内容。

这是服务器端日志:

Request.getContentLength(): 63
Content type: multipart/form-data; boundary=---------------------------194272772210834546661
Parm names:
Attribtue names:
__Attribute name: com.google.apphosting.runtime.jetty.APP_VERSION_REQUEST_ATTR

谁能帮我看看为什么我在客户端点击“提交”后在服务器上看不到任何文件?

提前致谢

编辑:

仍然无法弄清楚为什么我无法在服务器上获取表单数据。我正在关注this example,只是尝试将响应写入客户端,但服务器肯定看不到来自客户端的任何内容。

服务器代码:

try {
      log.info("Inside try block");
      ServletFileUpload upload = new ServletFileUpload();
      log.info("created the servlet file upload");
      res.setContentType("text/plain");
      log.info("set the content type to text/plain");
      FileItemIterator iterator = upload.getItemIterator(req);
      log.info("Got the iterator for items");
      while (iterator.hasNext()) {
        log.info("__inside iterator.hasNext");
        FileItemStream item = iterator.next();
        log.info("__assigned the file item stream");
        InputStream stream = item.openStream();
        log.info("__opened said stream");
        if (item.isFormField()) {
          log.warning("Got a form field: " + item.getFieldName());
        } else {
          log.warning("Got an uploaded file: " + item.getFieldName() +
              ", name = " + item.getName());

          int len;
          byte[] buffer = new byte[8192];
          while ((len = stream.read(buffer, 0, buffer.length)) != -1) {
            res.getOutputStream().write(buffer, 0, len);
          }
          log.info("Done writing the input to the output stream");
        }
      }
    } catch (Exception ex) {
      log.severe("Exception; " + ex);
      throw new ServletException(ex);
    }
    log.info("Done parseInput3");

日志:

Inside parseInput3
Inside try block
created the servlet file upload
set the content type to text/plain
Got the iterator for items
Done parseInput3

同样,它肯定无法遍历服务器上的文件项...知道为什么吗?

【问题讨论】:

    标签: google-app-engine gwt file-upload


    【解决方案1】:

    事实证明,GAE 有一种完全不同的文件(Blob)上传方式: http://code.google.com/appengine/docs/java/blobstore/overview.html#Uploading_a_Blob

    您需要为客户端上的表单提供来自服务器的 Blobstore 上传 URL(超时),使用以下方法检索:

    blobstoreService.createUploadUrl('urlToRedirectToAfterUploadComplete')
    

    在表单的操作上设置上传 URL 后,表单将被提交,并且 blobstore 服务将重定向到提供的 URL,然后可以访问由 Google 存储的对象的BlobKey

    因此,我将以下 ChangeHandler 添加到我的 GWT FileUpload

    private void addChangeListener() {
        Core.log("Selected file: " + uploader.getFilename());
        uploader.addChangeHandler(new ChangeHandler() {
          @Override
          public void onChange(ChangeEvent event) {
            MyApp.SERVICES.getUploadUrl(new SuccessAsyncCallback<String>() {
              @Override
              public void onSuccess(String uploadUrl) {
                form.setAction(uploadUrl);
                form.submit();
                Core.log("Submitted form with upload url: " + uploadUrl);
              }
            });
          }
        });
      }
    

    然后在 servlet 中,我在上传后将 GAE 重定向到:

     @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
        Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
        // where 'uploader' is the name of the FileUploader (<input type='file'>) control on the client
        List<BlobKey> blobKeys = blobs.get("uploader");
        resp.getOutputStream().print(blobKeys.get(0).getKeyString());
      }
    

    注意!

    如果FileUpload 控件没有定义name="whateveryouwantthenametobe" 属性,即使你告诉它(使用UiBinder)id 是ui:field="nameofControl",GAE 将在尝试获取上传的 blob 的值时抛出 OutOfMemory 异常

    【讨论】:

      【解决方案2】:

      您无法写入本地文件系统 - 您应该查看files api

      【讨论】:

      • 您能否就如何从客户端提取 GAE 上的上传文件提供任何建议?该 blobstore 链接仅显示如何创建文件并将其存储到 blobstore,而不显示如何提取上传的文件。
      猜你喜欢
      • 1970-01-01
      • 2012-05-23
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多