4

私のチームと私は、SafariとAppEngineの制限の組み合わせが原因で、すばらしいアニメーションアプリがSafariで動作しないことに不満を持っています。私たちはあなたの一人がそれを解決するための「魔法の呪文」を見つけるのを手伝ってくれることを望んでいます。

これは解決するのが非常に簡単な問題かもしれませんが、これはほとんど文書化されていない珍しい(非常に便利ですが)シナリオであるため、2日後にレンガの壁にぶつかっただけです。

問題の詳細を説明させてください。

私たちのアプリは、キャンバスデータをblobstore(ユーザーがアニメーション用に描画した画像)に保存する必要があります。通常、これを行うには、画像データを含むバイナリフィールドを持つajaxを介してWebフォームを動的に投稿します。これを行う1つの方法は、ArrayBufferとBlobBuilderを使用することです。これはChromeで機能します。

dataURItoBlob = function(dataURI, callback) {
  var ab, bb, byteString, i, ia, mimeString, _ref;
  if (!(typeof ArrayBuffer != "undefined" && ArrayBuffer !== null)) {
    return null;
  }
  byteString = atob(dataURI.split(',')[1]);
  mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  ab = new ArrayBuffer(byteString.length);
  ia = new Uint8Array(ab);
  for (i = 0, _ref = byteString.length; (0 <= _ref ? i < _ref : i > _ref); (0 <= _ref ? i += 1 : i -= 1)) {
    ia[i] = byteString.charCodeAt(i);
  }
  bb = window.BlobBuilder ? new BlobBuilder() : window.WebKitBlobBuilder ? new WebKitBlobBuilder() : window.MozBlobBuilder ? new MozBlobBuilder() : void 0;
  if (bb != null) {
    bb.append(ab);
    return bb.getBlob(mimeString);
  } else {
    return null;
  }
};
postCanvasToBlobstore = function(url, name, canvas) {
        blob = dataURItoBlob(canvas.toDataURL());
        formData = new FormData();
        formData.append("file", blob);
        xhr = new XMLHttpRequest();
        xhr.open("POST", url);
        return xhr.send(formData);
}

バイナリ形式のデータを保存する別の方法は、xhr.sendAsBinary()を使用することです。これはFirefoxで機能します。

postCanvasToBlobstore = function(url, name, canvas) {
  type='image/png'
  var arr, boundary, data, j, xhr;
  data = canvas.toDataURL(type);
  data = data.replace('data:' + type + ';base64,', '');
  xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  boundary = 'imaboundary';
  xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
    arr = ['--' + boundary, 'Content-Disposition: form-data; name="' + name + '"; filename="' + name + '"', 'Content-Type: ' + type, '', atob(data), '--' + boundary + '--'];
  j = arr.join('\r\n');
  return xhr.sendAsBinary(j);
}

これらの可能性はどちらもSafariには存在しないようです(可能性は非常に高いですが、それを理解するのに十分なほど賢くはありません)。1つの代替方法は、base64でエンコードされたデータを使用することです。これはSafariで確実に実行できます。これは次のようになります。

postCanvasToBlobstore = function(url, name, canvas, type) {
  type='image/png'
  var arr, boundary, data, j, xhr;
  data = canvas.toDataURL(type);
  data = data.replace('data:' + type + ';base64,', '');
  xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  boundary = 'imaboundary';
  xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
    arr = ['--' + boundary, 'Content-Disposition: form-data; name="' + name + '"; filename="' + name + '"', 'Content-Transfer-Encoding: base64','Content-Type: ' + type, '', data, '--' + boundary + '--'];
  j = arr.join('\r\n');
  return xhr.send(j);
}

今、これは実際に機能します!ただし、既知のblobstoreバグのため、AppEngineツールの開発バージョンでのみ機能します。アプリを本番環境にデプロイするとすぐに機能しなくなります。もちろん、POSTコードをどこかで微調整することで、blobstoreがデータを解釈する際の問題を解決できる可能性があります。この問題に関連するblobstoreの問題と思われるものについては、 http: //code.google.com/p/googleappengine/issues/detail?id=4265を参照してください。

上記の3つのコードサンプルのいずれかを編集コントロールに貼り付けて、postCanvasToBlobstore関数の各バージョンで何が起こるかを確認できます。最初のサンプルはChromeで機能し、2番目のサンプルはFirefoxで機能します(これはデバッグアプリのデフォルトのバージョンです)。 to)、そして3番目は3つすべてから機能するはずです(ただし、おそらくblobstoreのバグが原因で、この本番Webサイトを使用する場合はいずれも機能しません)。

4

2 に答える 2

3

これは、本番環境での処理方法のバグのようContent-Transfer-Encodingです。私はそれを社内で提出しましたが、それが解決されるのを待ちたくない場合(そして私はあなたがそうしないことを期待しています)、回避策が必要です。

幸い、最近、プログラムでblobstoreに書き込むことができるFiles APIをリリースしました。また、アップロードリクエストの本文の制限を32MBに増やしました。ペイロードがそのサイズ未満である限り、最も便利な形式でアップロードを受け入れるハンドラーを作成し、それを自分でblobstoreに保存できます。通常のアップロードメカニズムを維持することをお勧めします。これは、実際に使用する方が効率的であるためですが、それはあなた次第です。

AppEngineAPIへの個々の呼び出しにはまだサイズ制限があることに注意してください。ファイル全体を書き込むには、を複数回呼び出す必要がありますwrite。詳細については、この関連する質問に対する私の回答を参照してください。

于 2011-07-04T02:33:37.820 に答える
1

私がやっていることは、base64をキャンバスからrpcまで約25000文字からrpcまでシャード/チャンクし、それを900文字に分解して、データストアのtmpテーブルにTEXTとして保存します。それが終わったら、すべてがそこにあることを確認するためにいくつかのチェックを行います。次に、それをblobstoreにストリームデコードします。

ソースの一部を次に示します:GAEDatastore

さらに質問があります:branflake2267

この号にスターを付けてください。

App Engineフォーラムにコメントして、エンジニアにも表示されるようにしてください。

お役に立てば幸いです。

于 2011-07-04T03:07:56.553 に答える