@@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper
99import com.fasterxml.jackson.databind.node.JsonNodeType
1010import com.withorb.api.core.MultipartField
1111import com.withorb.api.errors.OrbInvalidDataException
12+ import java.io.ByteArrayInputStream
13+ import java.io.InputStream
1214import java.io.OutputStream
1315import kotlin.jvm.optionals.getOrNull
1416import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder
@@ -41,8 +43,18 @@ internal fun multipartFormData(
4143 MultipartEntityBuilder .create()
4244 .apply {
4345 fields.forEach { (name, field) ->
44- val node = jsonMapper.valueToTree<JsonNode >(field.value)
45- serializePart(name, node).forEach { (name, bytes) ->
46+ val knownValue = field.value.asKnown().getOrNull()
47+ val parts =
48+ if (knownValue is InputStream ) {
49+ // Read directly from the `InputStream` instead of reading it all
50+ // into memory due to the `jsonMapper` serialization below.
51+ sequenceOf(name to knownValue)
52+ } else {
53+ val node = jsonMapper.valueToTree<JsonNode >(field.value)
54+ serializePart(name, node)
55+ }
56+
57+ parts.forEach { (name, bytes) ->
4658 addBinaryBody(
4759 name,
4860 bytes,
@@ -55,16 +67,19 @@ internal fun multipartFormData(
5567 .build()
5668 }
5769
58- private fun serializePart (name : String , node : JsonNode ): Sequence <Pair <String , ByteArray >> =
70+ private fun serializePart (
71+ name : String ,
72+ node : JsonNode ,
73+ ): Sequence <Pair <String , InputStream >> =
5974 when (node.nodeType) {
6075 JsonNodeType .MISSING ,
6176 JsonNodeType .NULL -> emptySequence()
62- JsonNodeType .BINARY -> sequenceOf(name to node.binaryValue())
63- JsonNodeType .STRING -> sequenceOf(name to node.textValue().toByteArray ())
77+ JsonNodeType .BINARY -> sequenceOf(name to ByteArrayInputStream ( node.binaryValue() ))
78+ JsonNodeType .STRING -> sequenceOf(name to node.textValue().toInputStream ())
6479 JsonNodeType .BOOLEAN ->
65- sequenceOf(name to node.booleanValue().toString().toByteArray ())
80+ sequenceOf(name to node.booleanValue().toString().toInputStream ())
6681 JsonNodeType .NUMBER ->
67- sequenceOf(name to node.numberValue().toString().toByteArray ())
82+ sequenceOf(name to node.numberValue().toString().toInputStream ())
6883 JsonNodeType .ARRAY ->
6984 node.elements().asSequence().flatMap { element ->
7085 serializePart(" $name []" , element)
@@ -77,6 +92,8 @@ internal fun multipartFormData(
7792 null -> throw OrbInvalidDataException (" Unexpected JsonNode type: ${node.nodeType} " )
7893 }
7994
95+ private fun String.toInputStream (): InputStream = ByteArrayInputStream (toByteArray())
96+
8097 override fun writeTo (outputStream : OutputStream ) = entity.writeTo(outputStream)
8198
8299 override fun contentType (): String = entity.contentType
0 commit comments