【Dart/Flutter】httpパッケージを使ってMultipart形式のリクエストを送る
【Dart/Flutter】httpパッケージを使ってMultipart形式のリクエストを送る
概要
Dart や Flutter でHTTPリクエストを扱う際には既に定番となっている http パッケージですが、残念なことにMultipart形式のリクエストを簡単に送るためのメソッドが用意されていません。
SNSなどで提供されているWeb APIを使用して面白い画像や動画をプログラムからアップロードしたい場合にはほとんどの場合でMultipart形式のHTTPリクエストを送る必要がありますが、http パッケージでは自分でMultipart形式のリクエストを送る実装をしなければいけないので敬遠している方も少なくないのではないかと思います。
しかし、実際のところこれを実装するのはとても簡単で、この記事で紹介する手順を読めば必ず実装できるようになります。私が開発している twitter_api_v2 や mastodon_api で使用している実装でもあるので、その他の多くのWeb APIに対しても応用が可能です!
前提
この記事を読み進めるにあたっての前提事項です。
httpパッケージのインストール
まずは以下のお馴染みのコマンドで http パッケージをインストールしましょう。
Dart:
dart pub add http
Flutter:
flutter pub add http
また、必要に応じて以下のコマンドを実行しましょう。
Dart:
dart pub get
Flutter:
flutter pub get
実装
結論から始めると以下の実装で http パッケージを使用してMultipart形式のリクエストを送信可能です。
Future<void> main(List<String> args) async {
final response = await multipart(
method: 'POST',
url: Uri.https('xxxx.com', '/v1/api/something'),
files: [
http.MultipartFile.fromBytes(
'media',
File('./media/xxxx.jpg').readAsBytesSync(),
),
],
);
print(response.statusCode);
print(response.body);
}
Future<http.Response> multipart({
required String method,
required Uri url,
required List<http.MultipartFile> files,
}) async {
final request = http.MultipartRequest(method, url);
request.files.addAll(files); // 送信するファイルのバイナリデータを追加
request.headers.addAll({'Authorization': 'Bearer xxxxxx'}); // 認証情報などを追加
final stream = await request.send();
return http.Response.fromStream(stream).then((response) {
if (response.statusCode == 200) {
return response;
}
return Future.error(response);
});
}
HTTPについて詳しい方であれば上記の実装を見ただけでなんとなく理解できると思いますが、少し難しい実装であるため簡単に説明していきます。
Multipartリクエストを生成する
まず、Multipart形式のリクエストを送るためには、その名の通り MultipartRequest
オブジェクトを使用します。MultipartRequest
オブジェクトのインスタンスを生成する際には HTTPメソッドを表す文字列
と リクエストを送信する先のURL
が必要です。
final request = http.MultipartRequest(method, url);
例えば、上記の例に値を当てはめると以下のようになります。
final request = http.MultipartRequest(
'POST',
Uri.https('xxxx.com', '/v1/api/something'),
);
Multipartリクエストにファイルを設定する
Multipartリクエストを生成できたら、リクエストオブジェクトに実際に送信するファイルを設定してみましょう。以下のように設定できます。
final request = http.MultipartRequest(
'POST',
Uri.https('xxxx.com', '/v1/api/something'),
);
request.files.addAll(files);
ただ、MultipartRequest
の files
フィールドに設定できるファイルのオブジェクトは dart:io
の File
ではなく、 http:http.dart
の MultipartFile
であることに注意してください。
例えば、上記の例をより具体的に定義すると以下のようになります。
final request = http.MultipartRequest(
'POST',
Uri.https('xxxx.com', '/v1/api/something'),
);
request.files.addAll([
http.MultipartFile.fromBytes(
'media',
File('./media/xxxx.jpg').readAsBytesSync(),
),
]);
MultipartFile
オブジェクトの作り方はいくつかありますが、dart:io
の File
オブジェクトから作るのが楽です。上記の例だとファイルシステムから画像ファイルを取得し、バイトとして読み込んだ上で MultipartFile
オブジェクトに渡しています。
また、MultipartFile
を生成して、Multipart形式のリクエストを成功させるために重要になるのがフィールド名です。上記の例だと、MultipartFile.fromBytes
の第一引数である media
がフィールド名になります。
このフィールド名はGET通信時のクエリパラメータにおけるKEYのような役割を持ち、APIサーバーが受け取ったHTTPリクエストを処理する際に重要な名前になります。そのため、このフィールド名は必ず使用するAPIのリファレンスを読んで指定する名前を確認するようにしてください。
Multipartリクエストに認証情報を設定する
Web APIを使用して画像や動画をアップロードするということは、ユーザーの認証が必要になるサービスがほとんどではないかと思います。これはMultipart形式のリクエストに限った話ではないですが、認証情報はリクエストヘッダーに設定することが多いです。
例えば、今では定番となったOAuth 2.0のBearerトークンは以下のように設定できます。
request.headers.addAll({'Authorization': 'Bearer xxxxxx'});
Multipartリクエストを送信する
さて、ここまで来たら後はリクエストを送信するだけです。
final stream = await request.send();
単純に request.send()
を実行しただけでは StreamedResponse
が返ってくるので、より扱いやすい Response
オブジェクトの形式に変換するには以下のようにします。
final stream = await request.send();
return http.Response.fromStream(stream).then((response) {
if (response.statusCode == 200) {
return response;
}
return Future.error(response);
});
上記の例ではステータスコードが200の場合だけResponseオブジェクトを返却するようにしていますが、こうしなければいけないというわけではなく、必要に応じてカスタマイズしてください。
おまけ: MultipartリクエストにFormデータを設定する
様々なWeb APIのエンドポイントの中にはファイルのバイナリデータと一緒にFormデータを送信できるものがあります。こうしたユースケースであっても MultipartRequest
オブジェクトは対応可能です。
以下のようにファイルのバイナリデータと一緒に送信したいFormデータを設定できます。
request.fields.addAll({
'description': 'This is my funny photo!',
'alt_text': 'wdyt about it?',
});
最後に
ここまでDartのhttpパッケージを使用してMultipart形式のリクエストを送信する方法を紹介しました。Web APIを使用してプログラムから画像や動画をアップロードする方法がわかったかと思います。
もちろんこの記事で紹介した実装がすべてではありませんので、この記事で紹介した実装を実際に使用するWeb APIに応じてカスタマイズしていただいて構いません。
スポンサーの募集
オープンソース開発をサポートしてくださるスポンサーを募集しています。少額($1)からの寄付も可能ですので、以下のリンクから是非ご支援ください。
また、この記事にバッジを贈っていただくことでも支援は可能です。
Discussion