REST API - ファイル(画像など)処理 - ベストプラクティス 質問する

REST API - ファイル(画像など)処理 - ベストプラクティス 質問する

私たちは、JSON を受け入れて応答する REST API を備えたサーバーを開発しています。問題は、クライアントからサーバーに画像をアップロードする必要がある場合です。

注: また、ここでは、エンティティ (ユーザー) が複数のファイル (carPhoto、licensePhoto) を持ち、他のプロパティ (名前、電子メールなど) も持つことができるユースケースについて説明していますが、新しいユーザーを作成するときにこれらの画像は送信されず、登録プロセス後に追加されます。


私が知っている解決策は、それぞれに欠点がある。

1. JSONの代わりにmultipart/form-dataを使用する

良い点: POST および PUT リクエストは可能な限り RESTful であり、ファイルとともにテキスト入力を含めることができます。

短所: JSONではなくなったため、multipart/form-dataに比べてテストやデバッグなどがはるかに簡単になりました。

2. 個別のファイルの更新を許可する

新規ユーザーを作成するための POST リクエストでは画像の追加は許可されません (冒頭で述べたように、このユースケースでは問題ありません)。画像のアップロードは、たとえば /users/4/carPhoto への multipart/form-data として PUT リクエストによって行われます。

良い点: すべて (ファイルのアップロード自体を除く) が JSON のままなので、テストやデバッグが簡単です (長さを気にせずに完全な JSON リクエストをログに記録できます)

短所: 直感的ではありません。エンティティのすべての変数を一度に POST または PUT することはできません。また、このアドレスは/users/4/carPhotoコレクションとして考えることができます (REST API の標準的な使用例は次のようになります/users/4/shipments)。通常、エンティティの各変数を GET/PUT することはできません (また、そうしたくもありません)。たとえば、users/4/name などです。users/4 では、GET で名前を取得し、PUT で変更できます。ID の後に何かがある場合は、通常、users/4/reviews などの別のコレクションです。

3. Base64を使用する

JSON として送信しますが、ファイルは Base64 でエンコードします。

良い: 最初のソリューションと同じで、可能な限り RESTful なサービスです。

短所: 繰り返しになりますが、テストとデバッグは非常に悪くなります (本体にはメガバイトのデータが含まれる場合があります)。サイズが増加し、クライアントとサーバーの両方で処理時間も増加します。


私は本当に解決策 2 を使いたいのですが、欠点もあります... 「何が最善の」解決策なのかについて、より詳しい情報を提供してくれる人はいますか?

私の目標は、できるだけシンプルにしながら、できるだけ多くの標準を組み込んだ RESTful サービスを提供することにあります。

ベストアンサー1

OPです(2年経ってこの質問に答えています。Daniel Cerecedo の投稿は当時は悪くなかったのですが、Web サービスは非常に急速に発展しています)

フルタイムのソフトウェア開発(ソフトウェア アーキテクチャ、プロジェクト管理、マイクロサービス アーキテクチャにも重点を置いて)に 3 年間従事した後、私は間違いなく 2 番目の方法(ただし、一般的なエンドポイントは 1 つ)を最善の方法として選びました。

画像用の特別なエンドポイントがあれば、それらの画像の処理能力が大幅に向上します。

モバイル アプリ (iOS/Android) とフロントエンド (React を使用) の両方に同じ REST API (Node.js) があります。これは 2017 年なので、画像をローカルに保存するのではなく、クラウド ストレージ (Google Cloud、S3、Cloudinary など) にアップロードし、画像に対して何らかの一般的な処理が必要になります。

典型的なフローは、画像を選択するとすぐにバックグラウンドでアップロードが開始され (通常は /images エンドポイントの POST)、アップロード後に ID が返されるというものです。これは非常にユーザーフレンドリーです。ユーザーが画像を選択し、通常は他のフィールド (住所、名前など) に進むため、ユーザーが「送信」ボタンを押すと、画像は通常すでにアップロードされています。ユーザーは画面に「アップロード中...」と表示されるのを待って見守る必要はありません。

画像の取得についても同じことが言えます。特に携帯電話と限られたモバイル データのおかげで、元の画像を送信するのではなく、帯域幅をあまり消費しないようサイズ変更した画像を送信したいと考えるようになります (また、モバイル アプリを高速化するには、画像のサイズをまったく変更したくないことが多く、ビューにぴったり収まる画像が必要です)。このため、優れたアプリでは、Cloudinary のようなものが使用されています (または、サイズ変更用に独自の画像サーバーがあります)。

また、データがプライベートでない場合は、アプリ/フロントエンドに URL のみを送り返すと、クラウド ストレージから直接ダウンロードされます。これにより、サーバーの帯域幅と処理時間が大幅に節約されます。当社の大規模なアプリでは、毎月数テラバイトがダウンロードされるため、CRUD 操作に重点を置いた各 REST API サーバーでこれを直接処理することは望ましくありません。これを 1 か所 (キャッシュなどを備えた当社の Imageserver) で処理するか、クラウド サービスですべてを処理する必要があります。

2023 年の小さな更新: 可能であれば、写真の前に CDN を配置すると、通常、多くの費用を節約でき、写真がさらに利用しやすくなります (つまり、ピークが発生しても問題が発生しません)。


短所: 考えるべき唯一の「短所」は、「画像が割り当てられていない」ことです。ユーザーは画像を選択し、他のフィールドへの入力を続けます。その後、「いや」と言ってアプリまたはタブをオフにしますが、その間に画像は正常にアップロードされています。これは、どこにも割り当てられていない画像をアップロードしたことを意味します。

これを処理するにはいくつかの方法があります。最も簡単な方法は「気にしない」です。これは、このようなことがあまり頻繁に起こらない場合や、ユーザーが送信したすべての画像を(何らかの理由で)保存したいが削除したくない場合に有効です。

もう 1 つも簡単です。CRON があり、たとえば毎週、1 週間以上前の割り当てられていないイメージをすべて削除します。

おすすめ記事