web-dev-qa-db-ja.com

マルチパートHTTP応答

目標は、Node.js/ hapi APIサーバーがブラウザーのAJAXリクエストに2つのことで応答することです。

  • メディアファイル(例:画像)
  • ファイルに関するメタデータを含むJSONオブジェクト

これらは、バイナリデータをJSONに簡単に格納できないため、2つの別個のアイテムです。それ以外の場合、これは単一のリソースになります。それにもかかわらず、それらは単一の応答で送信されることが望ましい。

これらは、multipart/form-data。その場合、ブラウザーは本体をシリアル化する組み込みメカニズムを提供し、ほとんどのサーバー側フレームワークはそれを解析する方法を知っています。 しかし、どのようにして応答に対して同じように、反対方向に行うのですか?つまり、サーバーはどのように本文をシリアル化してクライアントに送信する必要がありますか?

私が言えることから、multipart/mixedは便利なコンテンツタイプである可能性があります。しかし、これについての話はほとんどありません。ほとんどの人は、各ピースに1つずつ、2つの別々のGETルートを提供することに頼っているようです。それはとりわけ、レースコンディションにあなたを開放するからです。何が欠けていますか?

hapijs/discuss#56 の私の質問も参照してください。

8
Seth Holladay

応答を_multipart/form-data_として提供し、Response.formData()を使用してクライアントで応答を読み取ることができます

_fetch("/path/to/server", {method:"POST", body:formData})
.then(response => response.formData())
.then(fd => {
  for (let [key, prop] of fd) {
    console.log(key, prop)
  }
})
_
_let fd = new FormData();
fd.append("json", JSON.stringify({
  file: "image"
}));
fetch("data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==")
  .then(response => response.blob())
  .then(blob => {
    fd.append("file", blob);
    new Response(fd)
      .formData()
      .then(formData => {
        for (let [key, data] of formData) {
          console.log(key, data)
        }
      })
  })_
5
guest271314

マルチパート形式を使用している場合、アップロード(POST/PUT)と取得(GET)の両方でまったく同じ形式を使用することに本質的に問題はないと思います。

HTTPを使用する場合、双方向で同じオンワイヤ形式を使用することには間違いなく優雅さがあると思います。

ただし、GETを使用してPUT/POSTおよびJSON中にフォームデータを送信する場合は、これが正しいことかどうかを質問し始めます。

multipartは、クライアントが画像を表示したいだけの場合、煩わしくなります。異なるエンドポイントを使用することを検討しましたか? 1つは画像用、もう1つはメタデータ用ですか?それらを1つのリソースに結合する必要がある理由は何ですか?

または、画像に情報を埋め込むこともできます。たとえばJPEGでは、EXIFを使用してカスタムデータを追加できます。少なくとも、画像を直接開くだけの機能は維持されます。

ただし、multipart/mixedは、画像とjsonオブジェクトを埋め込むだけの場合に適していますが、次の点に注意してください。

  1. それはおそらく消費には少し不便です
  2. それも少し珍しいです
  3. マルチパートエンコーディングでは、画像をいくつかの7ビッ​​トエンコーディングでエンコードする必要があると確信しています。これにより、本質的にリクエストサイズがかなり大きくなります。
2
Evert