Google App Engine


在代码包中你可以找到一个 gae-python 目录,它便是应用于 Google App Engine 的完整服务端示例:http://fileupload.cndoc.wiki/tree/v10.32.0/server/gae-python

由于该 demo 示例依赖于跨域连接(从 Github 页面到 App Engine),它必须以编程方式将文件写入 Blobstore,而不是使用直接上传功能。上传到 Blobstore 可提高上传性能并允许你上传大文件,但是,Blobstore 方式无法设置任何自定义 header,包括跨域访问所必需的 header。你可以在本指南末尾找到有关此问题的更多信息。

FileUpload 插件与 Google App Engine 的 Blobstore


要使用 FileUpload 插件将文件上传到 Google App EngineBlobstore,你需要在服务端实现基于表单的普通文件上传,并且返回的是一个 JSON 响应。

首先,你可以按照 Google 关于 Blobstore 文件上传的文档进行操作。然后,不要将用户重定向到上传的 blob,而是重定向到返回 JSON 响应的页面,该响应的内容应该是一个包含了所有文件上传信息的对象数组(请参阅安装指南)。

由于必须为 blobstore 的每个上传请求创建一个新的文件上传 url,你需要在服务端新建一个处理程序,该处理程序用来创建这些 url,并将它们作为浏览器 GET 请求的响应返回:

from google.appengine.ext import blobstore
from google.appengine.ext import webapp
class UploadUrlHandler(webapp.RequestHandler):
    def get(self):
        upload_url = blobstore.create_upload_url('/path/to/upload/handler')
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write('"' + upload_url + '"')

在客户端,你可以使用 submit 回调拿到用于上传的 url,并将其替代为 data.url,然后再发送文件到后端处理程序:

$('#fileupload').fileupload({
    submit: function (e, data) {
        var $this = $(this);
        $.getJSON('/upload-url-handler.json', function (result) {
            data.url = result;
            $this.fileupload('send', data);
        });
        return false;
    } 
});

另请参阅提交文件异步扩展插件扩展文档。

App Engine Blobstore 与跨域上传


由于我的 Demo 页面已经重写并托管在了 Github 上,而上传仍然提交到 App Engine,所以现在不得不解决跨域 Blobstore 问题。

首先,你可能希望先对此问题加星,这样 App Engine 开发团队在将来也许会让 Blobstore 上传 url 支持添加自定义 header 功能:http://code.google.com/p/googleappengine/issues/detail?id=5059。不过我觉得成功的可能性不大,因为上传 url 还必须对预检 OPTIONS 的请求返回响应。

当前 demo 通过一个自定义文件处理程序来接收上传的文件,然后再以编程方式将文件写入 blobstore(可以在代码包中的 gae 目录找到相关源码):http://code.google.com/appengine/docs/python/blobstore/overview.html#Writing_Files_to_the_Blobstore。遗憾的是,这不是最有效的解决方案 - 文件上传会受到 App Engine 实例的限制,包括文件大小上限和内存使用限制。

因此,我遵循 postMessage 方法,在最新版本的插件中添加了对它的支持。要使用 postMessage 传输文件上传,请将插件添加到 HTML 页面的脚本部分,并在插件初始化时启用 postMessage 配置项,其值需要指向 postmessage.html 文件的 URL。 postMessage 文件上传目前仅 Google Chrome 和 Firefox (8.0+) 支持,另外 Firefox 不允许使用 File、Blob 或 FileList 对象进行跨域 postMessage 传输(请参见该问题的进一步说明:https://bugzilla.mozilla.org/show_bug.cgi?id=673742)。