Sample code for 30+ languages & platforms
PureBasic

Send SOAP multipart/related with XML Body and Zip Attachment

See more REST Misc Examples

Demonstrates how to construct and send a multipart/related POST containing a SOAP XML body and a binary zip attachment.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkBinData.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkRest.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This example requires the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    ; This example constructs and sends the following HTTP request.
    ; (The boundary strings will be different and auto-generated by Chilkat)

    ; Accept-Encoding: gzip,deflate
    ; SOAPAction: invio
    ; Content-Type: Multipart/Related; boundary="MIME_boundary"; type="text/xml"; start="mailto:rootpart@soapui.org"
    ; MIME-Version: 1.0
    ; 
    ; --MIME_boundary
    ; Content-Type: text/xml; charset=UTF-8
    ; Content-Transfer-Encoding: 8bit
    ; Content-ID: <rootpart@soapui.org>
    ;  
    ; <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:attachment.ws.it">
    ; <soapenv:Header/>
    ; <soapenv:Body>
    ;   <urn:inputBean>
    ;    <nomeFileAllegato>myfile.zip</nomeFileAllegato>
    ;   </urn:inputBean>
    ; </soapenv:Body>
    ; </soapenv:Envelope>
    ;  
    ; --MIME_boundary
    ; Content-Type: application/zip
    ; Content-Transfer-Encoding: binary
    ; Content-ID: <myfile.zip>
    ; Content-Disposition: attachment; name="myfile.zip"; filename="myfile.zip"
    ; 
    ; ... binary zip data goes here ...
    ; --MIME_boundary--
    ; 

    rest.i = CkRest::ckCreate()
    If rest.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkRest::ckAddHeader(rest,"Accept-Encoding","gzip,deflate")
    CkRest::ckAddHeader(rest,"SOAPAction","invio")
    CkRest::ckAddHeader(rest,"Content-Type","Multipart/Related; boundary=" + Chr(34) + "MIME_boundary" + Chr(34) + "; type=" + Chr(34) + "text/xml" + Chr(34) + "; start=" + Chr(34) + "mailto:rootpart@soapui.org" + Chr(34))
    CkRest::ckAddHeader(rest,"MIME-Version","1.0")

    ; Build the SOAP XML:
    ; Use this online tool to generate the code from sample XML: 
    ; Generate Code to Create XML

    xml.i = CkXml::ckCreate()
    If xml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::setCkTag(xml, "soapenv:Envelope")
    CkXml::ckAddAttribute(xml,"xmlns:soapenv","http://schemas.xmlsoap.org/soap/envelope/")
    CkXml::ckAddAttribute(xml,"xmlns:urn","urn:attachment.ws.it")
    CkXml::ckUpdateChildContent(xml,"soapenv:Header","")
    CkXml::ckUpdateChildContent(xml,"soapenv:Body|urn:inputBean|nomeFileAllegato","myfile.zip")

    ; Build the SOAP XML sub-part
    CkRest::setCkPartSelector(rest, "1")
    CkRest::ckAddHeader(rest,"Content-Type","text/xml; charset=UTF-8")
    CkRest::ckAddHeader(rest,"Content-Transfer-Encoding","8bit")
    CkRest::ckAddHeader(rest,"Content-ID","<rootpart@soapui.org>")
    success = CkRest::ckSetMultipartBodyString(rest,CkXml::ckGetXml(xml))

    ; Build the sub-part containing the .zip
    CkRest::setCkPartSelector(rest, "2")
    CkRest::ckAddHeader(rest,"Content-Type","application/zip")
    CkRest::ckAddHeader(rest,"Content-Transfer-Encoding","binary")
    CkRest::ckAddHeader(rest,"Content-ID","<myfile.zip>")
    CkRest::ckAddHeader(rest,"Content-Disposition","attachment; name=" + Chr(34) + "myfile.zip" + Chr(34) + "; filename=" + Chr(34) + "myfile.zip" + Chr(34))

    ; Add a zip file to the 2nd sub-part body.
    ; This example will load the .zip file into memory, but it is also possible to stream directly from the file as the request is sent
    ; by calling SetMultipartBodyStream.
    bd.i = CkBinData::ckCreate()
    If bd.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkBinData::ckLoadFile(bd,"qa_data/zips/helloWorld.zip")
    success = CkRest::ckSetMultipartBodyBd(rest,bd)

    ; To be safe, always revert the PartSelector back to 0..
    CkRest::setCkPartSelector(rest, "0")

    ; Send the request by connecting to the web server and then sending..
    ; Connect using TLS.
    bAutoReconnect.i = 1
    success = CkRest::ckConnect(rest,"www.chilkatsoft.com",443,1,bAutoReconnect)
    If success <> 1
        Debug CkRest::ckLastErrorText(rest)
        CkRest::ckDispose(rest)
        CkXml::ckDispose(xml)
        CkBinData::ckDispose(bd)
        ProcedureReturn
    EndIf

    ; In this example, we're setting DebugMode.
    ; When debug mode is turned on, no request is actually sent.
    ; Instead, the request that would be sent is recorded to memory
    ; and we can retrieve it afterwards..
    CkRest::setCkDebugMode(rest, 1)

    responseStr.s = CkRest::ckFullRequestMultipart(rest,"POST","/someTargetPath")
    If CkRest::ckLastMethodSuccess(rest) <> 1
        Debug CkRest::ckLastErrorText(rest)
        CkRest::ckDispose(rest)
        CkXml::ckDispose(xml)
        CkBinData::ckDispose(bd)
        ProcedureReturn
    EndIf

    ; Retrieve the request that would've been sent and save it to a file.
    ; We can then examine the file to see if the request was structured as we desired.
    ; (Note: The zip bytes will be binary data and will appear as garbled garbage in a text editor..)
    bdRequest.i = CkBinData::ckCreate()
    If bdRequest.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkRest::ckGetLastDebugRequest(rest,bdRequest)
    success = CkBinData::ckWriteFile(bdRequest,"qa_output/multipartRelatedRequest.bin")

    Debug "OK, examine the output file.."


    CkRest::ckDispose(rest)
    CkXml::ckDispose(xml)
    CkBinData::ckDispose(bd)
    CkBinData::ckDispose(bdRequest)


    ProcedureReturn
EndProcedure