1

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ますか? たとえば、境界ではなく Content-Length を指定する方法はありますか?
  • データを取得するための GET リクエストでは、バイナリ データが返される文字列になると単純に期待できますか、それともサーバーが自動的にデータを何らかの方法でエンコードするのでしょうか?
  • エンコーディングを使用する必要がある場合、基本的にランダムな 8 ビット データに対してサポートされているオプションの中で、どれが最適ですか? (base-64、UTF-8、その他の何か?)
4

1 に答える 1

1

この質問でタンブルウィード バッジを受け取りましたが、気になる人がいる場合に備えて、進捗状況を報告させてください。

この質問は、3 つの独立した問題を引き起こすことが判明しました。

  1. BlobStore へのデータの効率的なアップロード
  2. BlobStore が可能な限り小さい形式で保存することを確認する
  3. データを確実にダウンロードする方法を見つける

(3) から始めましょう。これが最大の問題を引き起こします。

これまでのところ、XHR 経由で真の 8 ビット データをブラウザにダウンロードする方法を見つけることができませんでした。application/octet-stream のような MIME タイプを使用すると、データがファイルにダウンロードされない限り、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) について説明します。

着信帯域幅は無料なので、問題 (2) と (3) を優先して、問題 (1) を解決する優先度を下げることにしました。結局のところ、次の 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 文字で構成される base64-MIME エンコード データです ( http://en.wikipedia.org/wiki/Base64#Examplesを参照してください。GAEは最後の 2 文字として + と / を使用します)。文字列データで XHR send() 関数を呼び出すと、文字列の UTF-8 エンコードが行われ、サーバーが受信したデータが台無しになるため、エンコードが必要です (間違っている場合は修正してください)。残念ながら、ArrayBuffers と Blobs を send() 関数に渡すことは、まだすべてのブラウザーで利用できるわけではなく、この問題をよりエレガントに回避できます。

朗報です。AppEngine BlobStore は、このデータを自動的かつ正確にデコードし、オーバーヘッドなしで保存します。したがって、base64 エンコーディングを使用すると、クライアントからのデータ アップロードが遅くなるだけで、追加のホスティング コストは発生しません (デコードに数 CPU サイクルがかかる場合を除きます)。

余談: AppEngine 開発サーバーは、管理コンソールと取得された BlobInfo レコードの両方で、格納された BLOB のエンコードされたサイズ (つまり、33% 大きい) を報告します。ただし、運用サーバーにはこの問題はなく、正しい BLOB サイズが報告されます。

結論

文字 0x00、0x81、0x8D、0x8F、0x90、および 0x9D を含まない可能性があるbase64Content-Type のバイナリ データをアップロードするためにContent-Transfer-Encodingを使用すると、ストレージ/送信帯域幅のオーバーヘッドがある多くのテスト済みブラウザーで信頼性の高いデータ転送が行われます。 text/plain; charset=ISO-8859-10.5パーセント未満です。base64 でエンコードされたデータのアップロード オーバーヘッドは 33% であり、UTF-8 (ランダムな 8 ビット データの場合) で予想される 50% よりも優れていますが、それでも望ましいとは言えません。

私が知らないのは、これが最適な解決策なのか、それとももっとうまくできるのかということです。挑戦する人はいますか?

于 2012-08-04T17:22:58.663 に答える