我正在尝试找出从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位二进制数据。
具体来说,我试图理解以下内容:
boundary
?例如。有没有办法指定内容长度而不是边界?答案 0 :(得分:1)
即使我收到了Tumbleweed Badge这个问题,但是如果有人关心我的话,请让我报告我的进展:
这个问题最终引发了3个独立问题:
让我们从(3)开始,因为这最终会带来最大的问题:
到目前为止,我还没有找到通过XHR将真正的8位数据下载到浏览器的方法。除非将数据下载到文件中,否则使用像application / octet-stream这样的mime类型只会导致7位可靠地到达客户端。我找到的最佳解决方案是使用以下mime-type作为数据:
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位值,但有以下限制/注意事项:
总的来说,这使得我们可以使用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==
是base64-MIME编码的数据,包含上述250个允许的字符(请参阅http://en.wikipedia.org/wiki/Base64#Examples,GAE使用+和/作为最后2个字符)。编码是必要的(如果我错了,请纠正我),因为使用String数据调用XHR send()函数将导致字符串的UTF-8编码,这会破坏服务器接收的数据。不幸的是,在所有浏览器中都没有将ArrayBuffers和Blob传递给send()函数,而是为了更优雅地规避这个问题。
现在好消息:AppEngine BlobStore会自动正确地解码这些数据并存储它而不会产生任何开销!因此,使用base64编码只会导致客户端数据上传速度变慢,但不会导致额外的托管成本(除非可能需要几个CPU周期才能进行解码)。
除此之外:AppEngine开发服务器将在管理控制台和检索到的BlobInfo记录中报告存储的blob的编码大小(即大33%)。但是,生产服务器没有此问题,并报告正确的blob大小。
<强>结论强>:
使用Content-Transfer-Encoding base64
上传Content-Type text/plain; charset=ISO-8859-1
的二进制数据,其中可能不包含字符0x00,0x81,0x8D,0x8F,0x90和0x9D,从而获得可靠的数据转移许多经过测试的浏览器,其存储/传出带宽开销不到0.5%。 base64编码数据的上传开销为33%,优于UTF-8预期的50%(对于随机8位数据),但仍远远不够理想。
我不知道的是:这是最佳解决方案,还是可以做得更好?任何人都可以接受挑战吗?