如何使用 XmlHttpRequest 2.0 上传 5MB 文件到 App Engine BlobStore?

2 投票
2 回答
1360 浏览
提问于 2025-04-16 03:30

大家都知道,App Engine 对大多数输入/输出请求限制在 1 MB。不过,最近推出的 BlobStore API 允许你通过向动态生成的 URL 发送 POST 请求来上传大文件。

根据示例,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 技术来异步处理这个呢?这是我目前写的代码片段:

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 的内容发送的。这没问题,对于最多 1 MB 的文件,它可以正常工作,而不需要 BlobStore。在 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

但是我并没有使用带有 input type=file 的 HTML 表单,我是使用 XmlHttpRequest 的——我该如何让 App Engine “认为”这是来自 HTML 表单的文件,从而“获取”文件数据呢?

我的代码没有修改,结果却出现了错误。

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

2 个回答

1

大家普遍认为,目前App Engine的BlobStore上传接口只接受一种叫做“multipart编码”的POST数据,也就是说,你需要用一个HTML表单,里面有一个类型为file的输入框。或者,你可以使用Firefox浏览器,通过拖放的方式读取用户的二进制文件,利用FileReader API手动构建multipart编码。然后,你可以用XmlHttpRequest异步提交这些数据。

截至目前,Chrome和Safari浏览器不支持FileReader对象,所以它们无法拆分二进制文件,也就不能异步发送multipart编码的数据。

需要注意的是,如果文件大小在1MB以下,使用拖放加XmlHttpRequest的方式上传文件到App Engine在上述三种浏览器中仍然是有效的。

3

你可能会想看看我关于如何上传到blobstore的博客文章,这里有几个链接可以参考:第一部分第二部分第三部分(支持多次上传)。此外,还有这篇最近的食谱文章也很有帮助。

撰写回答