formData method
Implementation
Future<Map<String, Object?>> formData() async {
final contentType = headers.get('content-type');
if (contentType == null) return {};
final mediaType = MediaType.parse(contentType);
if (mediaType.mimeType == 'application/x-www-form-urlencoded') {
final text = await body.text();
return Uri.splitQueryString(text);
}
if (mediaType.mimeType == 'multipart/form-data') {
final boundary = mediaType.parameters['boundary'];
if (boundary == null) return {};
final transformer = MimeMultipartTransformer(boundary);
final parts = body.stream.transform(transformer);
final data = <String, Object?>{};
await for (final part in parts) {
final contentDisposition = part.headers['content-disposition'];
if (contentDisposition != null) {
final header = _HeaderValue.parse(contentDisposition);
final name = header.parameters['name'];
final filename = header.parameters['filename'];
if (name != null) {
if (filename != null) {
// It's a file
final bytes =
await part.fold<List<int>>([], (p, e) => p..addAll(e));
data[name] = MultipartFile(
filename: filename,
contentType: part.headers['content-type'],
bytes: bytes,
);
} else if (part.headers['content-type'] == dvFlatContentType) {
// A field packed as a binary flat buffer, which is what the
// transport spec asks for: over text multipart every value
// arrives as a String and the type is gone by the time a
// parameter is decoded.
//
// A damaged buffer is refused rather than falling back to text.
// Handing a parameter the raw bytes of a corrupt envelope is
// exactly the plausible-looking wrong value this is meant to
// prevent.
final bytes =
await part.fold<List<int>>(<int>[], (p, e) => p..addAll(e));
data[name] = dvFlatDecode(Uint8List.fromList(bytes));
} else {
// It's a field
final value = await utf8.decodeStream(part);
data[name] = value;
}
}
}
}
return data;
}
return {};
}