DEV Community

Cover image for ApidogでファイルアップロードAPI(multipart/form-data)をテストする方法
Akira
Akira

Posted on • Originally published at apidog.com

ApidogでファイルアップロードAPI(multipart/form-data)をテストする方法

ファイルを受け取るエンドポイントを実装したら、次はHTTP経由で実際に検証します。たとえば、ユーザーがプロフィール画像を POST /avatars にアップロードし、アプリケーションが署名済みPDFを POST /documents に送信するケースです。ローカルファイルを選択し、フォームフィールドへ添付して送信し、レスポンスまで確認できるテストを作成しましょう。

今すぐApidogを試す

ファイルアップロードでは、JSONではなく multipart/form-data を使います。そのため、JSONボディを貼り付けるだけではテストできません。ファイルフィールドを扱えるリクエストビルダーと、RunnerやCLIで実行するときにファイルを参照できる実行環境が必要です。Apidog では、単一・複数ファイルの送信、JSONメタデータの同時送信、レスポンスアサーション、Runner・CLIでのヘッドレス実行まで設定できます。

マルチパートリクエストの構造を先に確認したい場合は、APIでのファイルアップロードも参照してください。ブラウザ実装側では、MDNのFormDataリファレンスが参考になります。

multipart/form-dataとは何か、なぜアップロードに必要なのか

Apidogのリクエストボディでは、form-datax-www-form-urlencoded、JSON、XML、raw、binaryを選択できます。通常のAPI呼び出しではJSONを使うことが多い一方、ファイル送信ではform-dataを選択します。

form-dataは次のヘッダーに対応します。

Content-Type: multipart/form-data
Enter fullscreen mode Exit fullscreen mode

multipart/form-dataでは、リクエストボディが複数のパートに分割されます。各パートには名前と値があり、テキスト・数値・ファイルを同じリクエストに含められます。

たとえば、次のような構成です。

パート名 内容
title プロフィール画像
avatar PNGやJPEGなどのファイルバイト
metadata JSON文字列

x-www-form-urlencodedもキー・値形式ですが、ファイルのバイトデータを送る用途には向きません。ファイルを含む場合はform-data、短い文字列や数値だけを送るフォームではx-www-form-urlencodedを使います。

Apidogでは、form-dataの各パラメータに型を設定できます。ファイルを送るフィールドは、型をstringではなくfileに変更してください。これにより、値は文字列ではなく添付ファイルとして送信されます。

単一ファイルをアップロードしてレスポンスを検証する

ここでは、画像を受け取る次のエンドポイントを例にします。

POST /avatars
Enter fullscreen mode Exit fullscreen mode

リクエストはavatarフィールドで画像を受け取り、保存結果としてURLを含むJSONを返す想定です。

1. form-dataボディを選択する

Apidogで新しいリクエスト、または既存エンドポイントを開きます。

  • メソッド: POST
  • URL: https://api.example.com/avatars
  • Body: form-data

form-dataを選ぶと、Apidogはmultipart/form-dataとしてリクエストを構築します。

2. ファイルフィールドを追加する

次のパラメータを追加します。

Key Type Value
avatar file 選択した画像ファイル

ポイントは、avatarの型をstringからfileへ変更することです。型を変更すると、値入力欄がファイルピッカーに切り替わります。

3. ローカルファイルを選択する

avatar行のUploadをクリックし、たとえば次のファイルを選択します。

jane-profile.png
Enter fullscreen mode Exit fullscreen mode

Apidogは選択したファイルのローカルパスを参照して、送信時にファイルを読み込みます。

Apidogが保存するのはファイル本体ではなくローカルパスです。この挙動は、RunnerやCLIで実行する際に重要になります。

4. リクエストを送信する

Sendをクリックします。成功時のレスポンス例は次のとおりです。

{
  "id": "usr_8842",
  "avatarUrl": "https://cdn.example.com/avatars/usr_8842.png",
  "sizeBytes": 48210,
  "contentType": "image/png"
}
Enter fullscreen mode Exit fullscreen mode

5. レスポンスアサーションを追加する

ステータスコードだけでなく、レスポンスの内容も検証します。Apidogでは、エンドポイントまたはシナリオステップのリクエスト後アサーションに以下を追加します。

status code == 200
$.avatarUrl exists
$.contentType == "image/png"
Enter fullscreen mode Exit fullscreen mode

この例では、次の3点を確認しています。

  1. HTTPステータスが200である
  2. avatarUrlがレスポンスに存在する
  3. contentTypeimage/pngである

アサーションの設定方法やJSONPathの使い方は、APIアサーションガイドを参照してください。

同じリクエストをcurlで送る場合は、次のようになります。

curl -X POST https://api.example.com/avatars \
  -F "avatar=@jane-profile.png"
Enter fullscreen mode Exit fullscreen mode

curlの-Fはマルチパートフォームを構築するための指定です。@を付けると、値を文字列として送るのではなく、指定ファイルの内容を読み取ります。

ファイルとJSONを同時に送信する

実際のアップロードAPIでは、ファイルだけでなくメタデータを受け取ることが一般的です。

POST /documents
Enter fullscreen mode Exit fullscreen mode

たとえば、PDFとともにタイトル、カテゴリ、タグを送る場合を考えます。

単純なメタデータを送る

文字列や数値だけであれば、form-dataに通常のフィールドを追加します。

Key Type Value
title string Q3 Invoice
category string billing
file file q3-invoice.pdf

これらはすべて1つのmultipart/form-dataリクエストとして送信されます。

ネストしたJSONメタデータを送る

配列やネストしたオブジェクトを送る必要がある場合は、JSONを文字列パートとして送信します。

Apidogで次のパラメータを追加してください。

Key Type Value
file file q3-invoice.pdf
metadata string JSON文字列

metadataの値には、次のようなJSONをそのまま入力します。

{
  "title": "Q3 Invoice",
  "category": "billing",
  "tags": ["invoice", "2026", "paid"]
}
Enter fullscreen mode Exit fullscreen mode

サーバー側では、fileパートからPDFを読み取り、metadataパートをJSONとしてパースします。ファイルと通常フィールドを組み合わせる実例は、Stripeのファイルアップロードドキュメントでも確認できます。

Postmanから移行する場合は、PostmanでファイルとJSONデータをアップロードする方法も参考になります。

複数ファイルを送る

複数ファイルも、特別なモードは不要です。file型のパラメータを必要な数だけ追加します。

たとえば、メインファイルとサムネイルを受け取るAPIなら、次のように設定します。

Key Type
file file
thumbnail file

エンドポイントが期待するフィールド名に合わせて追加してください。

アップロードを繰り返し可能なテストシナリオにする

単発のリクエスト送信で動作を確認したら、回帰テスト用のシナリオに組み込みます。

たとえば、次のフローです。

  1. POST /avatarsで画像をアップロードする
  2. レスポンスからidを取得する
  3. GET /users/{id}を呼び出す
  4. アバターURLが永続化されていることを検証する

アップロードリクエストをシナリオの1ステップとして保存し、後続ステップでレスポンス値を利用します。ステップ間の値の受け渡しは、Apidogでテストシナリオを作成する方法で確認できます。

シナリオ化すると、次のような実行が可能になります。

ただし、ローカルでは成功したアップロードテストが、RunnerやCLIでは失敗することがあります。

落とし穴:別のマシンで実行するとファイルが見つからない

Apidogはファイル本体をクラウドへ保存するのではなく、選択したローカルファイルのパスを保存します。

たとえば、ローカルで次のファイルを選択したとします。

/Users/jane/pics/jane-profile.png
Enter fullscreen mode Exit fullscreen mode

このパスはJaneのラップトップ上では有効ですが、チームメイトのPC、Runnerコンテナ、CI環境には存在しません。

チームメイトが送信できないケース

チームメイトはリクエスト定義とファイルパスを見ることはできますが、そのパスが自分のディスク上に存在しないため送信できません。

対応方法は次のとおりです。

  1. チームメイトのマシンに同じテストファイルを配置する
  2. ファイルフィールドを開く
  3. 自分の環境にあるファイルパスへ変更する

Runnerで失敗するケース

Runnerでスケジュール実行するとき、RunnerホストがローカルPCのパスを参照することはできません。

Runnerでは、デプロイ時に-vでマウントしたホストディレクトリ内にファイルを置く必要があります。たとえば、Runnerから参照できるファイルを次の場所に配置します。

/opt/runner/jane-profile.png
Enter fullscreen mode Exit fullscreen mode

その後、シナリオのアップロードステップを開き、右上のBatch Editからファイルフィールドの値をRunner上のパスへ変更します。

/opt/runner/jane-profile.png
Enter fullscreen mode Exit fullscreen mode

CLIで失敗するケース

CLI実行でも同じです。CLIを実行するマシン上にテストファイルを配置し、シナリオ内のパスをその環境に合わせます。

例:

/opt/apidog/runner/jane-profile.png
Enter fullscreen mode Exit fullscreen mode

ハードコードせず環境変数で管理する

ローカル、Runner、CIごとにシナリオを編集したくない場合は、ファイルパスを変数化します。

たとえば、シナリオ内のファイルフィールドを次のような変数で設定します。

{{avatar_file_path}}
Enter fullscreen mode Exit fullscreen mode

そして環境ごとに値を設定します。

環境 avatar_file_path
ローカル /Users/jane/pics/jane-profile.png
Runner /opt/runner/jane-profile.png
CI /opt/apidog/runner/jane-profile.png

これにより、同じシナリオを使いながら、実行環境ごとにファイルの場所だけを切り替えられます。

Runnerがアクセスできるのは、-vでマウントしたディレクトリ配下のファイルだけです。マウント外のパスを指定しても、Runnerはファイルを読み取れません。

詳細は、ファイルアップロードリクエストに関するApidogドキュメントを参照してください。

Apidog CLIでアップロードシナリオを自動実行する

保存したシナリオは、CI環境でヘッドレス実行できます。

まず、CLIをインストールして認証します。

npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
Enter fullscreen mode Exit fullscreen mode

続いて、シナリオIDと環境IDを指定して実行します。

apidog run --access-token $APIDOG_ACCESS_TOKEN -t <scenario_id> -e <env_id> -r cli
Enter fullscreen mode Exit fullscreen mode

主なオプションは以下です。

オプション 用途
-t テストシナリオID
-e 環境ID
-r レポーター指定

レポーターにはclihtmljunitを指定できます。複数のレポーターを使う場合はカンマ区切りです。

apidog run \
  --access-token $APIDOG_ACCESS_TOKEN \
  -t <scenario_id> \
  -e <env_id> \
  -r cli,junit
Enter fullscreen mode Exit fullscreen mode

CLIは終了コードで成功・失敗を返すため、CIパイプラインの品質ゲートとして使えます。セットアップはApidog CLIインストールガイドを参照してください。

ただし、CLI実行時にもファイルはCLIマシン上に存在する必要があります。アップロード用ファイルを事前に配置し、Batch Editまたは環境変数で正しいパスを指定してください。

データ駆動テストを含むCI設定については、Apidog CLIを使用したデータ駆動型テストも参考になります。

よくある質問

チームメイトがファイルアップロードリクエストを送信できないのはなぜですか?

Apidogはファイル本体ではなくローカルパスを保存します。あなたのパスはあなたのPC上のファイルを指しており、チームメイトのPCには存在しません。

チームメイト側でファイルを配置し、ファイルフィールドを自分のローカルパスに変更してください。Runnerやスケジュールされたテストでも同じ考え方です。

同じリクエストでファイルとJSONを送るにはどうすればよいですか?

ボディタイプをform-dataにします。

  • ファイル用のパラメータを追加し、型をfileにする
  • JSON用のパラメータを追加し、型をstringにする
  • JSONを文字列値として入力する

サーバーは1つのマルチパートリクエストから、ファイルパートとJSON文字列パートを受け取れます。

Runnerではどのパスを使うべきですか?

-vでRunnerにマウントしたホストディレクトリ配下のパスを指定します。

例:

/opt/runner/yourfile.jpg
Enter fullscreen mode Exit fullscreen mode

ファイルをマウント済みディレクトリへコピーした後、Batch Editでアップロードフィールドのパスを更新してください。

ファイルサイズやファイル形式の制限はありますか?

実際の制限は、Apidogではなくテスト対象APIの実装によって決まります。API側のバリデーション仕様を確認し、次のケースをアサーションで検証してください。

  • サイズ上限を超えたファイル
  • 許可されていないMIMEタイプ
  • 拡張子と実体が異なるファイル
  • 空ファイル
  • 必須ファイルフィールドがないリクエスト

アップロードではform-datax-www-form-urlencodedのどちらを使うべきですか?

ファイルを送るならform-dataを使用します。

form-datamultipart/form-dataとして送信され、画像・PDFなどのバイトデータを含められます。x-www-form-urlencodedは、ファイルを含まない短い文字列・数値フィールド向けです。

まとめ

ファイルアップロードテストで重要なのは、次の2点です。

  1. multipart/form-dataリクエストを正しく構築する
  2. テストを実行する環境からファイルにアクセスできるようにする

Apidogでは、Bodyをform-dataに設定し、対象フィールドの型をfileへ変更してファイルを選択します。JSONメタデータが必要な場合は、別のstringフィールドにJSONを入力します。送信後は、ステータスコードだけでなく、URL・MIMEタイプ・IDなどもアサーションで検証してください。

RunnerやCLIへ移行する場合は、実行先マシンにファイルを配置し、Batch Editまたは環境変数でファイルパスを設定します。これにより、ローカルテストと自動テストで同じシナリオを安定して実行できます。

まずはApidogをダウンロードし、自分のアップロードエンドポイントにform-dataリクエストを送って検証してみてください。

Top comments (0)