@@ -5,6 +5,8 @@ package org.onebusaway.core.http
5
5
import com.fasterxml.jackson.databind.JsonNode
6
6
import com.fasterxml.jackson.databind.json.JsonMapper
7
7
import com.fasterxml.jackson.databind.node.JsonNodeType
8
+ import java.io.ByteArrayInputStream
9
+ import java.io.InputStream
8
10
import java.io.OutputStream
9
11
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder
10
12
import org.apache.hc.core5.http.ContentType
@@ -36,8 +38,18 @@ internal fun multipartFormData(
36
38
MultipartEntityBuilder .create()
37
39
.apply {
38
40
fields.forEach { (name, field) ->
39
- val node = jsonMapper.valueToTree<JsonNode >(field.value)
40
- serializePart(name, node).forEach { (name, bytes) ->
41
+ val knownValue = field.value.asKnown()
42
+ val parts =
43
+ if (knownValue is InputStream ) {
44
+ // Read directly from the `InputStream` instead of reading it all
45
+ // into memory due to the `jsonMapper` serialization below.
46
+ sequenceOf(name to knownValue)
47
+ } else {
48
+ val node = jsonMapper.valueToTree<JsonNode >(field.value)
49
+ serializePart(name, node)
50
+ }
51
+
52
+ parts.forEach { (name, bytes) ->
41
53
addBinaryBody(
42
54
name,
43
55
bytes,
@@ -50,16 +62,19 @@ internal fun multipartFormData(
50
62
.build()
51
63
}
52
64
53
- private fun serializePart (name : String , node : JsonNode ): Sequence <Pair <String , ByteArray >> =
65
+ private fun serializePart (
66
+ name : String ,
67
+ node : JsonNode ,
68
+ ): Sequence <Pair <String , InputStream >> =
54
69
when (node.nodeType) {
55
70
JsonNodeType .MISSING ,
56
71
JsonNodeType .NULL -> emptySequence()
57
- JsonNodeType .BINARY -> sequenceOf(name to node.binaryValue())
58
- JsonNodeType .STRING -> sequenceOf(name to node.textValue().toByteArray ())
72
+ JsonNodeType .BINARY -> sequenceOf(name to ByteArrayInputStream ( node.binaryValue() ))
73
+ JsonNodeType .STRING -> sequenceOf(name to node.textValue().toInputStream ())
59
74
JsonNodeType .BOOLEAN ->
60
- sequenceOf(name to node.booleanValue().toString().toByteArray ())
75
+ sequenceOf(name to node.booleanValue().toString().toInputStream ())
61
76
JsonNodeType .NUMBER ->
62
- sequenceOf(name to node.numberValue().toString().toByteArray ())
77
+ sequenceOf(name to node.numberValue().toString().toInputStream ())
63
78
JsonNodeType .ARRAY ->
64
79
node.elements().asSequence().flatMap { element -> serializePart(name, element) }
65
80
JsonNodeType .OBJECT ->
@@ -73,6 +88,8 @@ internal fun multipartFormData(
73
88
)
74
89
}
75
90
91
+ private fun String.toInputStream (): InputStream = ByteArrayInputStream (toByteArray())
92
+
76
93
override fun writeTo (outputStream : OutputStream ) = entity.writeTo(outputStream)
77
94
78
95
override fun contentType (): String = entity.contentType
0 commit comments