| Index: pkg/http/lib/src/multipart_request.dart
|
| diff --git a/pkg/http/lib/src/multipart_request.dart b/pkg/http/lib/src/multipart_request.dart
|
| index 4d744c12210b55f67678667bb9413c3eb1886ff7..357aa7e17e4569a58605a37ff8aa38098d2e1c1d 100644
|
| --- a/pkg/http/lib/src/multipart_request.dart
|
| +++ b/pkg/http/lib/src/multipart_request.dart
|
| @@ -11,6 +11,7 @@ import 'dart:uri';
|
| import 'dart:utf';
|
|
|
| import 'base_request.dart';
|
| +import 'byte_stream.dart';
|
| import 'multipart_file.dart';
|
| import 'utils.dart';
|
|
|
| @@ -51,7 +52,7 @@ class MultipartRequest extends BaseRequest {
|
| encodeUtf8(value).length + "\r\n".length;
|
| });
|
|
|
| - for (var file in files) {
|
| + for (var file in _files.collection) {
|
| length += "--".length + _BOUNDARY_LENGTH + "\r\n".length +
|
| _headerForFile(file).length +
|
| file.length + "\r\n".length;
|
| @@ -68,33 +69,40 @@ class MultipartRequest extends BaseRequest {
|
| /// The form fields to send for this request.
|
| final Map<String, String> fields;
|
|
|
| - /// The files to upload for this request.
|
| - final List<MultipartFile> files;
|
| + /// The sink for files to upload for this request.
|
| + ///
|
| + /// This doesn't need to be closed. When the request is sent, whichever files
|
| + /// are written to this sink at that point will be used.
|
| + Sink<MultipartFile> get files => _files;
|
| +
|
| + /// The private version of [files], typed so that the underlying collection is
|
| + /// accessible.
|
| + final CollectionSink<MultipartFile> _files;
|
|
|
| /// Creates a new [MultipartRequest].
|
| MultipartRequest(String method, Uri url)
|
| : super(method, url),
|
| fields = <String>{},
|
| - files = <MultipartFile>[];
|
| + _files = new CollectionSink<MultipartFile>(<MultipartFile>[]);
|
|
|
| - /// Freezes all mutable fields and returns an [InputStream] that will emit the
|
| - /// request body.
|
| - InputStream finalize() {
|
| + /// Freezes all mutable fields and returns a single-subscription [ByteStream]
|
| + /// that will emit the request body.
|
| + ByteStream finalize() {
|
| // TODO(nweiz): freeze fields and files
|
| var boundary = _boundaryString(_BOUNDARY_LENGTH);
|
| headers['content-type'] = 'multipart/form-data; boundary="$boundary"';
|
| headers['content-transfer-encoding'] = 'binary';
|
| super.finalize();
|
|
|
| - var stream = new ListInputStream();
|
| + var controller = new StreamController<List<int>>.singleSubscription();
|
|
|
| void writeAscii(String string) {
|
| assert(isPlainAscii(string));
|
| - stream.write(string.charCodes);
|
| + controller.add(string.charCodes);
|
| }
|
|
|
| - void writeUtf8(String string) => stream.write(encodeUtf8(string));
|
| - void writeLine() => stream.write([13, 10]); // \r\n
|
| + writeUtf8(String string) => controller.add(encodeUtf8(string));
|
| + writeLine() => controller.add([13, 10]); // \r\n
|
|
|
| fields.forEach((name, value) {
|
| writeAscii('--$boundary\r\n');
|
| @@ -103,19 +111,19 @@ class MultipartRequest extends BaseRequest {
|
| writeLine();
|
| });
|
|
|
| - Futures.forEach(files, (file) {
|
| + Futures.forEach(_files.collection, (file) {
|
| writeAscii('--$boundary\r\n');
|
| writeAscii(_headerForFile(file));
|
| - return writeInputToInput(file.finalize(), stream)
|
| + return writeStreamToSink(file.finalize(), controller)
|
| .then((_) => writeLine());
|
| }).then((_) {
|
| // TODO(nweiz): pass any errors propagated through this future on to
|
| // the stream. See issue 3657.
|
| writeAscii('--$boundary--\r\n');
|
| - stream.markEndOfStream();
|
| + controller.close();
|
| });
|
|
|
| - return stream;
|
| + return new ByteStream(controller);
|
| }
|
|
|
| /// All character codes that are valid in multipart boundaries. From
|
|
|