通过HTTP请求将二进制数据上传到AppEngineBlobstore

Upload binary data to AppEngine Blobstore via HTTP request

本文关键字:AppEngineBlobstore 数据 二进制 HTTP 请求 通过      更新时间:2024-02-09

我正试图找出从JavaScript启动的HTTP请求上传/下载二进制数据到Google AppEngine的Blobstore的最低数据开销方法。理想情况下,我想直接提交二进制数据,即作为未编码的8位值;可能在POST请求中,看起来像这样:

...
Content-Type: multipart/form-data; boundary=boundary;
--boundary
Content-Disposition: form-data; name="a"; filename="b"
Content-Type: application/octet-stream
@#^%(^Qtr...
--boundary--

这里,@#^%(^Qtr...理想地表示任意8位二进制数据。

具体来说,我正在努力理解以下内容:

  • 是否可以直接上传8位二进制数据,或者我是否需要以某种方式对数据进行编码,比如base-64 MIME编码
  • 如果我使用不同的编码,Blobstore会在内部将数据保存为8位二进制还是以编码格式保存?也就是说,base-64编码会使我的存储成本增加33%吗
  • 同理:编码开销是否会增加传出带宽成本
  • 有没有更好的方法来格式化POST请求,这样我就不需要出现在二进制数据中的boundary了?例如,有没有一种方法可以指定内容长度而不是边界
  • 在检索数据的GET请求中,我是否可以简单地期望二进制数据最终出现在返回字符串中,或者服务器是否会以某种方式自动编码数据
  • 如果我需要使用某种编码,在基本上随机的8位数据支持的选项中,哪一个是最好的选择?(base-64,UTF-8,其他什么?)

尽管我收到了这个问题的汤博乐徽章,但无论如何,让我报告我的进展,以防有人关心:

这个问题提出了三个独立的问题:

  1. 高效地将数据上传到Blob存储
  2. 确保BlobStore以尽可能小的格式保存
  3. 找到可靠下载数据的方法

让我们从(3)开始,因为这最终提出了最大的问题:

到目前为止,我还没能找到一种通过XHR将真正的8位数据下载到浏览器的方法。使用mime类型(如application/octet流)只会导致7位可靠地到达客户端,除非数据被下载到文件中。我发现的最好的解决方案是对数据使用以下mime类型:

text/plain; charset=ISO-8859-1

这似乎在我测试过的所有浏览器中都支持:IE 8、Chrome 21、FF 12.0、Opera 11.61、Windows下的Safari 5.1.2和Android 2.3.3。

这样,几乎可以传输任何8位值,但有以下限制/注意事项:

  • 字符0x00在IE8中被解释为输入字符串的末尾,因此必须避免
  • 大多数浏览器将字符集ISO-8859-1解释为Windows-1252,从而相应地更改字符0x80到0x9F。不过,这是可以修复的,因为更改是明确的。(参见http://en.wikipedia.org/wiki/Windows-1252#Codepage_layout)
  • 字符0x81、0x8D、0x8F、0x90、0x9D保留在Windows-1252字符集中,Opera会返回这些字符的错误代码,因此也需要避免这些字符

总的来说,我们可以使用256个字符中的250个。由于需要对数据进行基本更改,这意味着传出数据开销低于0.5%,我想我可以接受。

所以,现在来看问题(1)和(2):

由于传入带宽是免费的,我决定将解决问题(1)的优先级降低到问题(2)和(3)。事实证明,使用以下POST请求就可以了:

...
Content-Type: multipart/form-data; boundary=-
---
Content-Disposition: form-data; name="a"; filename="b"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: base64
abcd==
-----

这里,abcd==是由上述250个允许的字符组成的base64MIME编码数据(参见http://en.wikipedia.org/wiki/Base64#Examples,GAE使用+和/作为最后2个字符)。编码是必要的(如果我错了,请纠正我),因为用String数据调用XHR send()函数会导致字符串的UTF-8编码,这会破坏服务器接收到的数据。不幸的是,并不是所有浏览器都可以将ArrayBuffers和Blob传递到send()函数,以更优雅地规避这个问题。

现在好消息是:AppEngineBlobStore会自动正确地解码这些数据,并在没有开销的情况下存储它!因此,使用base64编码只会导致从客户端上传数据的速度变慢,但不会导致额外的托管成本(除非解码可能需要几个CPU周期)。

此外:AppEngine开发服务器将在管理控制台和检索到的BlobInfo记录中报告存储blob的编码大小(即大33%)。但是,生产服务器没有此问题,并报告了正确的blob大小

结论

使用内容传输编码base64上载内容类型text/plain; charset=ISO-8859-1的二进制数据(可能不包含字符0x00、0x81、0x8D、0x8F、0x90和0x9D),对于许多存储/传出带宽开销小于0.5%的测试浏览器来说,可以实现可靠的数据传输。base64编码数据的上传开销为33%,这比UTF-8(针对随机8位数据)预期的50%要好,但仍远未达到要求。

我不知道的是:这是最佳解决方案,还是可以做得更好?有人愿意挑战吗?

相关文章:
  • 没有找到相关文章