StreamedMultipartExtractable class final

Hands a multipart/form-data body to the handler a part at a time.

The difference from MultipartExtractable, which buffers the whole body: this never holds more than one chunk, so an upload can be written straight to disk or to object storage. That is what makes a file larger than memory possible at all.

The cost is that the parts are ordered and consumable once. A handler that needs to look at part three before part one has to buffer, and should use the buffering extractor instead.

Future<Map<String, Object?>> upload(Request request) async {
  final body = await request.extract(const StreamedMultipartExtractable());
  var bytes = 0;

  await body.forEachPart((part) async {
    if (!part.isFile) return;
    final file = File('uploads/${newId()}').openWrite();
    bytes = await part.writeTo(file, limit: 50 * 1024 * 1024);
    await file.close();
  });

  return {'bytes': bytes};
}

limit bounds the whole body, and it is enforced as the bytes flow rather than up front: a streamed upload usually arrives without a content-length, so there is nothing to check before reading. A part that pushes the total past it fails with 413 mid-stream, which is the earliest anything can.

Implemented types

Constructors

StreamedMultipartExtractable({int limit = 64 * 1024 * 1024})
Streams the multipart body, capped at limit bytes in total.
const

Properties

hashCode → int
The hash code for this object.
no setterinherited
limit → int
The maximum total body size, in bytes.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited

Methods

extract(Request request) → Future<Result<StreamedMultipart, Rejection>>
Produces the value, or the rejection that stops the handler.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited