使用GWT和AppEngine上Blob存储多文件上传?(Multiple file upload

2019-08-05 11:04发布

我将如何去建立一个现代化的,Gmail的状,多个文件中GWT和AppEngine上Blob存储上传?

最常提出的解决方案是gwtupload ,通过马诺洛Carrasco的书面优异GWT组件。 然而,最新版本0.6.6不Blob存储(至少我无法得到它的工作)工作,它不支持多个文件中进行选择。 有多个文件中最新的0.6.7快照选择一个补丁,但虽然它允许多个文件选择(使用HTML5的“多”属性),它在剧照一个大POST请求发送他们(显示为进度文件一大堆)。

也有上因此,对于这个其他问题(例如这里或点击这里 ),但答案通常采用HTML5“多”的属性,并将其发送作为一个大POST请求。 它的工作原理,但它不是我后。

Answer 1:

尼克·约翰逊写了一些伟大的博客文章这件事。 他使用一种名为通用和广为接受的JavaScript组件上传Plupload ,并上传文件到Python编写的的AppEngine应用程序内。 Plupload支持支持多文件选择(HTML5,闪光,Silverlight的,等等)不同的后端( 运行时间 )和处理上传进度及其他相关的上传客户端事件。

他的解决方案的问题是:(1)它是在Python,和(2)它是在JavaScript。 这是GWT-plupload进入图片。 这是一个JSNI -wrapper为Plupload由Samuli雅维拉,这使GWT环境中使用Plupload编写的。 然而,该项目已过期(自2010年以来没有提交),但我们可以用它寻找灵感。

因此,对于构建多文件上传组件一步一步的说明如下。 这都将是一个项目,但它(尤其是JSNI的包装器)可以提取到其自己的.jar文件或库中的其他项目中获得重用。 源代码可以在这里到位桶 。

该应用可以在AppEngine上(不计费,所以不要指望它是可用或工作)在http://gwt-gaemultiupload-example.appspot.com/ 。

截图

第1步 - Servlet的

Blob存储在工作方式如下:

  1. 客户端请求的Blobstore它可用于上传文件的URL。
  2. 客户端职位文件接收到的URL。
  3. 当接收到整个POST,Blob存储将客户端重定向到一个成功的URL(创建上传URL时指定)。

为了支持这一点,我们将需要两个servlet。 一个用于生成的URL文件上传(请注意,每个文件上传需要一个唯一的URL),一个用于接收完成上传。 双方将非常简单。 下面是URL生成的servlet,这将只是写在纯文本的HTTP响应的URL。

public class BlobstoreUrlGeneratorServlet extends HttpServlet {     
    private static BlobstoreService blobstore = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Content-Type", "text/plain");
        resp.getWriter().write(blobstore.createUploadUrl("/uploadfinished"));
    }
}

然后,该servlet用于接收上传成功,这将打印的BlobKey到System.out

public class BlobstoreUploadFinishedServlet extends HttpServlet {
    private static BlobstoreService blobstore = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Map<String, List<BlobKey>> blobs = blobstore.getUploads(req);
        List<BlobKey> blobKeyList = blobs.get("file");

        if (blobKeyList.size() == 0)
            return;

        BlobKey blobKey = blobKeyList.get(0);

        System.out.println("File with blobkey " + blobKey.getKeyString() + " was saved in blobstore.");
    }
}

我们还需要在注册这些web.xml

<servlet>
    <servlet-name>urlGeneratorServlet</servlet-name>
    <servlet-class>gaemultiupload.server.BlobstoreUrlGeneratorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>urlGeneratorServlet</servlet-name>
    <url-pattern>/generateblobstoreurl</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>uploadFinishedServlet</servlet-name>
    <servlet-class>gaemultiupload.server.BlobstoreUploadFinishedServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>uploadFinishedServlet</servlet-name>
    <url-pattern>/uploadfinished</url-pattern>
</servlet-mapping>

如果我们现在运行应用程序,并参观http://127.0.0.1:8888/generateblobstoreurl ,我们会看到类似

http://<computername>:8888/_ah/upload/ahpnd3QtZ2FlbXVsdGl1cGxvYWQtZXhhbXBsZXIbCxIVX19CbG9iVXBsb2FkU2Vzc2lvbl9fGAEM 

如果我们发布一个文件到URL,将它保存在Blob存储区。 但是请注意,为当地开发网络服务器的默认URL是http://127.0.0.1:8888/同时通过Blob存储生成的URL是http://<computername>:8888/ 。 这将导致问题以后,为安全起见Plupload将无法将文件POST到其他域。 这只能与本地开发服务器发生,已发布的应用将只有一个URL。 通过编辑在Eclipse中运行配置对其进行修复,添加-bindAddress <computername>的论点。 这将导致本地开发服务器主机上的web应用程序http://<computername>:8888/来代替。 您可能需要允许<computername>的GWT浏览器插件为它这个改变后加载的应用程序。

到目前为止好,我们有我们需要的servlet。

第2步 - Plupload

下载Plupload(我用的是最新版本,1.5.4),解压缩,拷贝js文件夹到war在我们的GWT应用程序目录。 在这个例子中,我们不会使用jquery.plupload.queuejquery.ui.plupload ,我们将创建自己的GUI。 我们还需要jQuery的,这是我从下载了谷歌的API 。

接下来,我们需要在我们的应用程序的JavaScript的,所以编辑index.html ,并添加以下的<head>标记。

<script type="text/javascript" language="javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" language="javascript" src="js/plupload.full.js"></script>

所以,现在我们已在我们的应用程序Plupload。 接下来,我们需要把它包起来,以便能够与GWT使用它。 这是第一个使用GWT-plupload。 我没有从项目中使用的jar文件,而是复制的源文件,以便能够进行修改它们。 该包装的主要对象是Plupload类,它是通过构造PluploadBuilder 。 另外还有界面PluploadListener ,它可以实现为接收客户端事件。

第3步 - 将其组合在一起

所以,现在,我们需要在我们的GWT应用程序实际使用Plupload。 我增加了以下一个Index.ui.xml UiBinder的:

<g:Button text="Browse" ui:field="btnBrowse" />
<g:Button text="Start Upload" ui:field="btnStart" /><br />
<br />
<h:CellTable width="600px" ui:field="tblFiles" />

有用于浏览文件的按钮,一键即可开始上传,而我们将用它来显示上传状态CellTable。 在Index.java ,我们初始化Plupload如下:

btnBrowse.getElement().setId("btn-browse");
PluploadBuilder builder = new PluploadBuilder();
builder.runtime("html5");
builder.useQueryString(false);
builder.multipart(true);
builder.browseButton(btnBrowse.getElement().getId());
builder.listener(this);
plupload = builder.create();
plupload.init();

runtime属性告诉Plupload其此后端使用(我只测试了HTML5,但其他人也能正常运行)。 Blob存储需要multipart启用。 我们还需要设置浏览按钮的ID,然后告诉Plupload使用该ID。 单击此按钮将弹出Plupload的文件选择对话框。 最后,我们添加自己为收听(实施PluploadListener )和create()init() Plupload。

要显示准备上传的文件,我们只是需要将数据添加到tblFilesDataProvider从事件列表数据提供商UploadListener

@Override
public void onFilesAdded(Plupload p, List<File> files) {
    tblFilesDataProvider.getList().addAll(files);
}

为了显示进度,我们简单地更新,每当我们被告知的进步已经改变了列表:

@Override
public void onFileUploadProgress(Plupload p, File file) {
    tblFilesDataProvider.refresh();
}

我们还实施一个单击处理btnStart ,其甫一告诉Plupload开始上传。

@UiHandler("btnStart")
void btnStart_Click(ClickEvent event) {
    plupload.start();
}

现在可以选择的文件,他们将被添加到待处理的上传列表,我们可以开始上传。 唯一的一块左边是实际使用我们先前实施的servlet。 目前,Plupload不知道要发布的网址上传到,所以我们需要告诉它。 这是我已改变到GWT-plupload源代码(除了小错误修正); 我加入Plupload一个函数调用fetchNewUploadUrl 。 它所做的是它执行在我们前面definied获取上传的URL servlet的一个Ajax GET请求。 为此,它会同步(为什么会清楚后)。 当请求返回时,它设置此URL作为POST URL的Plupload。

private native void fetchNewUploadUrl(Plupload pl) /*-{
    $wnd.$.ajax({
        url: '/generateblobstoreurl',
        async: false,
        success: function(data) {
          pl.settings.url = data;
        },
    });
}-*/;

public void fetchNewUploadUrl() {
    fetchNewUploadUrl(this);
}

Plupload将张贴在自己的POST请求的每个文件。 这意味着我们需要每次上传开始之前,给它一个新的URL。 幸运的是,有一个在该事件PluploadListener ,我们可以实现。 这里的原因要求必须是同步的原因:否则,我们在下面(的事件处理程序收到的上传网址之前上传将开始pl.fetchNewUploadUrl()会立即返回)。

@Override
public void onBeforeUpload(Plupload pl, File cast) {
    pl.fetchNewUploadUrl();
}

就是这样! 你现在有GWT HTML5多文件上传功能把文件中的AppEngine Blob存储!

传递参数

如果你想额外的参数(如给其上传的文件所属的实体的ID),我添加了关于如何添加一个例子。 有一个方法PluploadsetExtraValue()我实现为:

public native void setExtraValue(String value) /*-{
    this.settings.multipart_params = {extravalue: value}
}-*/;

额外的值可以作为传递multipart_params 。 这是一个地图,所以功能可以扩展到让许多任意键 - 值对。 该值可以在被设置onBeforeUpload()的事件处理程序

@Override
public void onBeforeUpload(Plupload pl, File cast) {
    pl.setExtraValue(System.currentTimeMillis() + " is unique.");
    pl.fetchNewUploadUrl();
}

和在servlet检索接收完成上传作为

String value = req.getParameter("extravalue");

示例项目包含此示例代码。

最后的话

我是没有办法的专家GWT开发。 这是我想出了挫折后几个小时没有找到我之后的功能。 我得到了它的工作之后,我想我应该写了一个完整的例子,因为每个组件/博客文章的/ etc我用/跟着离开了某一部分进行。 我的意思不是以任何方式这是最佳实践的代码。 意见,改进和建议,欢迎!



文章来源: Multiple file upload using GWT and AppEngine Blobstore?