@@ -637,6 +637,13 @@ module HttpStatusCodes =
637637
638638type MultipartItem = MultipartItem of formField : string * filename : string * content : Stream
639639
640+ type MultipartFileItem =
641+ | MultipartFileItem of formField : string * filename : string option * contentType : string option * content : Stream
642+
643+ type MultipartFormDataItem =
644+ | FileValue of MultipartFileItem
645+ | FormValue of string * string
646+
640647/// The body to send in an HTTP request
641648type HttpRequestBody =
642649
@@ -649,6 +656,9 @@ type HttpRequestBody =
649656 /// A sequence of formParamName * fileName * fileContent groups
650657 | Multipart of boundary : string * parts : seq<MultipartItem>
651658
659+ /// A sequence of formParamName * fileName * fileContent groups
660+ | MultipartFormData of boundary : string * parts : seq<MultipartFormDataItem>
661+
652662/// The response body returned by an HTTP request
653663type HttpResponseBody =
654664 | Text of string
@@ -1521,7 +1531,7 @@ module internal HttpHelpers =
15211531 /// c) write newline
15221532 /// d) write section data
15231533 /// 3) write trailing boundary
1524- let writeMultipart ( boundary : string ) ( parts : seq < MultipartItem >) ( e : Encoding ) =
1534+ let writeMultipartFileItem ( boundary : string ) ( parts : seq < MultipartFileItem >) ( e : Encoding ) =
15251535 let newlineStream () =
15261536 new MemoryStream( e.GetBytes " \r\n " ) :> Stream
15271537
@@ -1545,18 +1555,23 @@ module internal HttpHelpers =
15451555
15461556 let segments =
15471557 parts
1548- |> Seq.map ( fun ( MultipartItem ( formField , fileName , contentStream )) ->
1549- let fileExt = Path.GetExtension fileName
1550- let contentType = defaultArg ( MimeTypes.tryFind fileExt) " application/octet-stream"
1558+ |> Seq.map ( fun ( MultipartFileItem ( formField , fileName , contentType , contentStream )) ->
15511559 let printHeader ( header , value ) = sprintf " %s : %s " header value
15521560
1553- let headerpart =
1554- [ prefixedBoundary
1555- HttpRequestHeaders.ContentDisposition( " form-data" , Some formField, Some fileName)
1556- |> printHeader
1557- HttpRequestHeaders.ContentType contentType
1558- |> printHeader ]
1559- |> String.concat " \r\n "
1561+ let headers =
1562+ match contentType with
1563+ | Some ( contentType) ->
1564+ [ prefixedBoundary
1565+ HttpRequestHeaders.ContentDisposition( " form-data" , Some formField, fileName)
1566+ |> printHeader
1567+ HttpRequestHeaders.ContentType contentType
1568+ |> printHeader ]
1569+ | None ->
1570+ [ prefixedBoundary
1571+ HttpRequestHeaders.ContentDisposition( " form-data" , Some formField, fileName)
1572+ |> printHeader ]
1573+
1574+ let headerpart = headers |> String.concat " \r\n "
15601575
15611576 let headerStream =
15621577 let bytes = e.GetBytes headerpart
@@ -1583,6 +1598,16 @@ module internal HttpHelpers =
15831598 let wholePayloadLength = wholePayload |> trySumLength
15841599 new CombinedStream( wholePayloadLength, wholePayload) :> Stream
15851600
1601+ let writeMultipart ( boundary : string ) ( parts : seq < MultipartItem >) ( e : Encoding ) =
1602+ let fileParts =
1603+ parts
1604+ |> Seq.map ( fun ( MultipartItem ( formField , fileName , stream )) ->
1605+ let fileExt = Path.GetExtension fileName
1606+ let contentType = defaultArg ( MimeTypes.tryFind fileExt) " application/octet-stream"
1607+ MultipartFileItem( formField, Some fileName, Some contentType, stream))
1608+
1609+ writeMultipartFileItem boundary fileParts e
1610+
15861611 let asyncCopy ( source : Stream ) ( dest : Stream ) =
15871612 async {
15881613 do !
@@ -2080,6 +2105,21 @@ type Http private () =
20802105
20812106 HttpContentTypes.FormValues, ( fun e -> new MemoryStream( bytes e) :> _)
20822107 | Multipart ( boundary, parts) -> HttpContentTypes.Multipart( boundary), writeMultipart boundary parts
2108+ | MultipartFormData ( boundary, parts) ->
2109+ let fileParts =
2110+ parts
2111+ |> Seq.map ( fun p ->
2112+ match p with
2113+ | FormValue ( formField, value) ->
2114+ MultipartFileItem(
2115+ formField,
2116+ None,
2117+ None,
2118+ new MemoryStream( Encoding.UTF8.GetBytes( value))
2119+ )
2120+ | FileValue ( item) -> item)
2121+
2122+ HttpContentTypes.Multipart( boundary), writeMultipartFileItem boundary fileParts
20832123
20842124 // Set default content type if it is not specified by the user
20852125 let encoding =
0 commit comments