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