bodyAsFormData method

Future<Map<String, FormField>> bodyAsFormData()

Decodes multipart/form-data body

Example: server.post('/upload', (ctx) async { final Map<String, FormField> formData = await ctx.req.bodyAsFormData(); BinaryFileFormField pic = formData'pic'; File file = new File('bin/data/' + pic.filename); IOSink sink = file.openWrite(); await sink.addStream(pic.value); await sink.close(); return Response.redirect(Uri.parse("/")); });

Implementation

Future<Map<String, FormField>> bodyAsFormData() async {
  if (_parsedFormData != null) {
    return _parsedFormData!;
  }

  if (req.headers.contentType == null ||
      !req.headers.contentType!.parameters.containsKey('boundary')) {
    throw Exception(
        'request does not contain boundary specification for form-data');
  }

  final String boundary = req.headers.contentType!.parameters['boundary']!;

  final ret = <String, FormField>{};

  final Stream<List<int>> bodyStream = await bodyAsStream;

  // Transform body to [MimeMultipart]
  final transformer = MimeMultipartTransformer(boundary);
  final Stream<MimeMultipart> stream = transformer.bind(bodyStream);

  await for (MimeMultipart part in stream) {
    HttpMultipartFormData multipart = HttpMultipartFormData.parse(part);

    // Parse field content type
    final ContentType? contentType = multipart.contentType;

    final String name = multipart.contentDisposition.parameters['name']!;

    final String? fn = multipart.contentDisposition.parameters['filename'];

    // Create field
    if (fn is! String && multipart.isText) {
      final String data = await multipart.join();
      final field = StringFormField(name, data, contentType: contentType);
      ret[field.name] = field;
    } else if (multipart.isText) {
      final field = TextFileFormField(name, multipart.cast<String>(),
          contentType: contentType, filename: fn);
      if (ret[name] is TextFileListFormField) {
        (ret[name] as TextFileListFormField).values.add(field);
      } else if (ret[name] is TextFileFormField) {
        ret[name] = TextFileListFormField.fromValues(
            [ret[name]! as TextFileFormField, field]);
      } else {
        ret[name] = field;
      }
    } else {
      final field = BinaryFileFormField(name, multipart.cast<List<int>>(),
          contentType: contentType, filename: fn);
      if (ret[name] is BinaryFileListFormField) {
        (ret[name] as BinaryFileListFormField).values.add(field);
      } else if (ret[name] is BinaryFileFormField) {
        ret[name] = BinaryFileListFormField.fromValues(
            [ret[name]! as BinaryFileFormField, field]);
      } else {
        ret[name] = field;
      }
    }
  }

  _parsedFormData = ret;
  return ret;
}