33

私はbackbone.jsで構築された単一のWebページアプリから消費されるjsonRESTWebサービスを開発しています

このAPIを使用すると、プロジェクトに関連するpdfレポートなど、一部のエンティティに関連するファイルをコンシューマーがアップロードできます。

グーグルで調べてスタックオーバーフローで調査を行うと、次のようなアプローチが考えられます。

最初のアプローチ: base64でエンコードされたデータフィールド

POST: /api/projects/234/reports
{
  author: 'xxxx',
  abstract: 'xxxx',
  filename: 'xxxx',
  filesize: 222,
  content: '<base64 encoded binary data>'
}

2番目のアプローチ:マルチパートフォームの投稿:

POST: /api/projects/234/reports
{
  author: 'xxxx',
  abstract: 'xxxx',
}

応答としてレポートIDを取得し、それを使用して別の投稿を発行します

POST: /api/projects/234/reports/1/content
enctype=multipart/form-data

バイナリデータを送信するだけです

(これを見てください:https ://stackoverflow.com/a/3938816/47633 )

3番目のアプローチ:バイナリデータを別のリソースに投稿し、hrefを保存します

まず、クライアントでランダムキーを生成し、そこにバイナリコンテンツを投稿します

POST: /api/files/E4304205-29B7-48EE-A359-74250E19EFC4
enctype=multipart/form-data

その後

POST: /api/projects/234/reports
{
  author: 'xxxx',
  abstract: 'xxxx',
  filename: 'xxxx',
  filesize: 222,
  href: '/api/files/E4304205-29B7-48EE-A359-74250E19EFC4'
}

(これを参照してください:https ://stackoverflow.com/a/4032079/47633 )

私が使用できる他のアプローチがあるかどうか、それぞれの長所/短所、そしてこの種の要件に対処するための確立された方法があるかどうかを知りたかっただけです

最初のアプローチで私が目にする大きな欠点は、クライアントでファイルを完全にロードしてbase64でエンコードする必要があることです。

いくつかの有用なリソース:

4

3 に答える 3

8

頭のてっぺんから他のアプローチは考えられません。

あなたの 3 つのアプローチのうち、私は方法 3 を最も多く使用しました。私が見る最大の違いは、最初の方法と他の 2 つの方法の違いです: メタデータとコンテンツを 2 つのリソースに分離する

  • 長所: スケーラビリティ
    • ソリューションには同じサーバーへの投稿が含まれますが、これはコンテンツのアップロードを別のサーバー (つまり、Amazon S3) にポイントするように簡単に変更できます。
    • 最初の方法では、ユーザーにメタデータを提供する同じサーバーで、大規模なアップロードによってプロセスがブロックされます。
  • 短所: 孤立したデータ/追加された複雑さ
    • 失敗したアップロード (メタデータまたはコンテンツのいずれか) は、孤立したデータをサーバー DB に残します
    • 孤立したデータはスケジュールされたジョブでクリーンアップできますが、これによりコードが複雑になります
    • 方法 II は孤立の可能性を減らしますが、最初の POST の応答をブロックしているため、クライアントの待機時間が長くなります

最初の方法は、コーディングが最も簡単に思えます。ただし、このサービスの使用頻度が低く、ユーザー ファイルのアップロードに妥当な制限を設定できる場合は、最初の方法のみを使用します。

于 2013-02-23T05:12:43.397 に答える
5

究極の方法は 3 (別のリソース) であると考えています。主な理由は、HTTP 標準から得られる価値を最大化できるためです。これは、REST API に対する私の考え方と一致します。たとえば、十分に根拠のある HTTP クライアントが使用されていると仮定すると、次の利点が得られます。

  • コンテンツの圧縮: クライアントがサポートを示している場合、サーバーが圧縮された結果で応答できるようにすることで最適化します。API は変更されず、既存のクライアントは引き続き動作し、将来のクライアントはそれを利用できます。
  • キャッシング: If-Modified-Since、ETag など。クライアントは、バイナリ データを完全に再フェッチすることを避けることができます。
  • コンテンツ タイプの抽象化: たとえば、アップロードされた画像が必要な場合、タイプimage/jpegまたはimage/png. HTTP ヘッダーのAcceptContent-typeは、スキーマや API の一部としてすべてをハードコーディングすることなく、クライアントとサーバーの間でこれをネゴシエートするための洗練されたセマンティクスを提供します。

一方、問題のバイナリ データがオプションではない場合、この方法は最も単純ではないと結論付けるのが妥当だと思います。その場合、 Eric Hu の回答に記載されている短所が有効になります。

于 2014-09-05T09:50:45.717 に答える