Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library multipart_file; | |
| 6 | |
| 7 import 'dart:io'; | |
| 8 | |
| 9 import 'utils.dart'; | |
| 10 | |
| 11 /// A file to be uploaded as part of a [MultipartRequest]. This doesn't need to | |
| 12 /// correspond to a physical file. | |
| 13 class MultipartFile { | |
| 14 /// The name of the form field for the file. | |
| 15 final String field; | |
| 16 | |
| 17 /// The size of the file in bytes. This must be known in advance, even if this | |
| 18 /// file is created from an [InputStream]. | |
| 19 final int length; | |
| 20 | |
| 21 /// The basename of the file. May be null. | |
| 22 final String filename; | |
| 23 | |
| 24 /// The content-type of the file. Defaults to `application/octet-stream`. | |
| 25 final ContentType contentType; | |
| 26 | |
| 27 /// The stream that will emit the file's contents. | |
| 28 final InputStream _stream; | |
| 29 | |
| 30 /// Whether [finalize] has been called. | |
| 31 bool get isFinalized => _isFinalized; | |
| 32 bool _isFinalized = false; | |
| 33 | |
| 34 /// Creates a new [MultipartFile] from an [InputStream]. The length of the | |
| 35 /// file in bytes must be known in advance. If it's not, read the data from | |
| 36 /// the stream and use [MultipartFile.fromBytes] instead. | |
| 37 /// | |
| 38 /// [contentType] currently defaults to `application/octet-stream`, but in the | |
| 39 /// future may be inferred from [filename]. | |
| 40 MultipartFile(this.field, this._stream, this.length, | |
| 41 {this.filename, ContentType contentType}) | |
| 42 : this.contentType = contentType != null ? contentType : | |
| 43 new ContentType("application", "octet-stream"); | |
| 44 | |
| 45 /// Creates a new [MultipartFile] from a byte array. | |
| 46 /// | |
| 47 /// [contentType] currently defaults to `application/octet-stream`, but in the | |
| 48 /// future may be inferred from [filename]. | |
| 49 factory MultipartFile.fromBytes(String field, List<int> value, | |
| 50 {String filename, ContentType contentType}) { | |
| 51 var stream = new ListInputStream(); | |
| 52 stream.write(value); | |
| 53 stream.markEndOfStream(); | |
| 54 return new MultipartFile(field, stream, value.length, | |
| 55 filename: filename, | |
| 56 contentType: contentType); | |
| 57 } | |
| 58 | |
| 59 /// Creates a new [MultipartFile] from a string. | |
| 60 /// | |
| 61 /// The encoding to use when translating [value] into bytes is taken from | |
| 62 /// [contentType] if it has a charset set. Otherwise, it defaults to UTF-8. | |
| 63 /// [contentType] currently defaults to `text/plain; charset=utf-8`, but in | |
| 64 /// the future may be inferred from [filename]. | |
| 65 factory MultipartFile.fromString(String field, String value, | |
| 66 {String filename, ContentType contentType}) { | |
| 67 contentType = contentType == null ? new ContentType("text", "plain") : | |
| 68 // Make a copy of the original contentType so we can modify charset. | |
|
Bob Nystrom
2012/11/07 00:50:26
If this is the motivation, maybe add a clone metho
nweiz
2012/11/07 20:53:29
I think there's a broader language-level (or at le
| |
| 69 new ContentType.fromString(contentType.toString()); | |
| 70 var charset = contentType.charset; | |
| 71 var encoding = encodingForCharset(contentType.charset, Encoding.UTF_8); | |
| 72 contentType.charset = encoding.name; | |
| 73 | |
| 74 return new MultipartFile.fromBytes(field, encodeString(value, encoding), | |
| 75 filename: filename, | |
| 76 contentType: contentType); | |
| 77 } | |
| 78 | |
| 79 // TODO(nweiz): Infer the content-type from the filename. | |
| 80 /// Creates a new [MultipartFile] from a [File]. | |
| 81 /// | |
| 82 /// [filename] defaults to the name of the file on disk. [contentType] | |
| 83 /// currently defaults to `application/octet-stream`, but in the future may be | |
| 84 /// inferred from [filename]. | |
| 85 static Future<MultipartFile> fromFile(String field, File file, | |
| 86 {String filename, ContentType contentType}) { | |
| 87 if (filename == null) filename = new Path(file.name).filename; | |
| 88 return file.length().transform((length) { | |
| 89 return new MultipartFile(field, file.openInputStream(), length, | |
| 90 filename: filename, | |
| 91 contentType: contentType); | |
| 92 }); | |
| 93 } | |
| 94 | |
| 95 // Finalizes the file in preparation for it being sent as part of a | |
| 96 // [MultipartRequest]. This returns an [InputStream] that should emit the body | |
| 97 // of the file. The stream may be closed to indicate an empty file. | |
| 98 InputStream finalize() { | |
| 99 if (finalized) { | |
| 100 throw new StateError("Can't finalize a finalized MultipartFile."); | |
| 101 } | |
| 102 _isFinalized = true; | |
| 103 return _stream; | |
| 104 } | |
| 105 } | |
| OLD | NEW |