【问题标题】:How do I upload a 5 MB file to App Engine BlobStore using XmlHttpRequest 2.0?如何使用 XmlHttpRequest 2.0 将 5 MB 文件上传到 App Engine BlobStore?
【发布时间】:2010-08-31 02:03:29
【问题描述】:

我们都知道,对于大多数输入/输出请求,App Engine 将您限制为 1 MB。但是使用最近的 BlobStore API,您可以通过 POST 到动态生成的 URL 来完整上传大文件。

根据示例,HTML 表单如下所示:

self.response.out.write('<html><body>')
self.response.out.write('<form action="%s" method="POST" 
  enctype="multipart/form-data">' % upload_url)
  self.response.out.write("""Upload File: 
<input type="file" name="file"><br> 
<input type="submit" name="submit" value="Submit"> 
</form></body></html>""")

但是我们如何使用 HTML5 引入的 JavaScript 技术异步执行此操作?这是我目前所拥有的 sn-p:

xhr.open("POST", post_url); // the post URL given by App Engine
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('X-File-Name', file.fileName);

// After loading the binary data (last time we only read as base64 string)
// Tell xhr to start the upload
myBinaryDataReader.addEventListener("loadend", function(evt){
   xhr.sendAsBinary(evt.target.result);
}, false);

// Initiate the binary reading on the file, when finished it will 
// upload asynchronously 
myBinaryDataReader.readAsBinaryString(file);

您会注意到,这种技术将原始二进制文件作为POST 正文发送。这很好,它不需要 BlobStore 最多 1 MB 就可以工作。在 Python 中,要读取文件,我只需使用:

img_data = self.request.body # got my image data now

但是,对于 BlobStore,我应该使用

upload_files = self.get_uploads('file')  # 'file' is file upload field in the form

但我没有使用输入 type=file 的 HTML 表单,我使用的是 XmlHttpRequest —— 如何让 App Engine“认为”它是来自 HTML 表单的文件,因此“抓取”文件数据?

我的代码,未经修改,导致错误

File "C:\Python26\lib\cgi.py", line 583, in keys
    raise TypeError, "not indexable"
TypeError: not indexable

【问题讨论】:

  • 另外,有没有办法将原始 POST 正文放入 App Engine 的 BlobStore?

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


【解决方案1】:

您可能想查看我关于上传到 blobstore 的博文(123)以及 this recent cookbook post

【讨论】:

  • 感谢您对此提供了很多启示。看起来我可能很不走运,因为使这项工作的部分仅在 Firefox 中有效。这是因为只有 Firefox 支持直接读取文件,并进行多部分编码,不幸的是 App Engine 目前需要 BlobStore。看来我必须切换到亚马逊 s3。
  • PLUpload,我在文章后面部分使用的,支持多种上传方式,任何现代浏览器都应该支持至少一种。其他所有方法都失败了,使用动态生成的 URL 的常规表单上传,如食谱帖子中的那样,可以正常工作。
  • 是的,这是一个非常好的库,我可以使用它。我开始意识到我的问题是服务器端的问题,而不是客户端的问题。我已经能够在 Chrome 5、Safari 4 和 Firefox 3.6 中通过浏览器、拖放和 XmlHttpRequests 成功提交二进制文件。如果我使用自己的 PHP 服务器,那么接受二进制数据服务器端并存储大图像将没有问题。但是,对于 App Engine,截至目前,BlobStore 仅接受具有多部分编码的表单——换句话说,非 XmlHttpRequests(除非您使用的是 Firefox)
  • 您可以在 XmlHTTPRequest 中使用多部分编码 - 您只需要自己创建多部分编码。
  • 确实可以 Nick,但是如果您打算使用多部分编码对已删除的文件进行编码,您现在只能在 Firefox 中进行。这是因为 Chrome 和 Safari 无权读取二进制文件数据(尽管它们可以将原始文件作为 POST 正文发送)。
【解决方案2】:

普遍的共识是,到目前为止,App Engine 的 BlobStore 上传 API 将只接受多部分编码的 POST 数据……换句话说,HTML 输入类型=文件形式。或者,您可以使用 Firefox 通过 FileReader API 读取用户的二进制文件(通过拖放)并手动重建多部分编码。然后就可以通过 XmlHttpRequest 异步提交数据了。

在撰写本文时,Chrome 和 Safari 不支持 FileReader 对象,因此它们无法拆分二进制文件,因此无法异步发送多部分编码。

请注意,如果小于 1 MB,将文件上传到 App Engine 的拖放 + XmlHttpRequest 方法在上述所有 3 种浏览器中仍然有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    相关资源
    最近更新 更多