| 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
 | 
| 
 |