Search code examples
vb.netweb-servicessoapmtom

Parsing raw mtom to construct file


Somehow I ended up with the problem to consume a SOAP endpoint with and aspx page that runs vb. Sending files and simple data works but I am stuck on downloading the file again.

For the MTOM response I just regex for the content in and parse it as XElement which works. Now for the binary stream I tried the same but was not yet successful. See below code for calling the endpoint and getting the result back.

Private Function sendSOAPRequest(url As String, enpoint As String, data As Byte()) As String
            Dim result As String = ""
            Try
                Dim req = WebRequest.Create(url)
                req.Headers.Add("SOAPAction", url + enpoint)

                req.ContentType = "application/soap+xml"
                req.ContentLength = data.Length
                req.Method = "POST"

                Dim DataStream = req.GetRequestStream()
                DataStream.Write(data, 0, data.Length)
                DataStream.Close()

                Dim WebResponse = req.GetResponse()
                Dim resp = WebResponse.GetResponseStream()
                Dim Reader = New StreamReader(resp)
                result = Reader.ReadToEnd()

                DataStream.Close()
                Reader.Close()
                resp.Close()
            Catch ex As WebException
                System.Diagnostics.Debug.WriteLine(ex.ToString())
            End Try
            System.Diagnostics.Debug.WriteLine(result)
            Return result

        End Function

Now for login/logout/upload this works. Now for some fileContent call I get this back:

HTTP/1.1 200 OK
X-Powered-By: Undertow/1
Access-Control-Allow-Headers: accept, authorization, content-type, x-requested-with
Server: WildFly/10
Date: Fri, 12 Apr 2019 12:06:58 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Type: multipart/related; type="application/xop+xml"; boundary="uuid:6c8ac7c2-cac9-437f-a319-72c7c0e60328"; start="<[email protected]>"; start-info="application/soap+xml"
Content-Length: 5371
Access-Control-Max-Age: 1
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT

--uuid:6c8ac7c2-cac9-437f-a319-72c7c0e60328
Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml"
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Body><ns2:getContentObjectStreamResponse xmlns:ns2="http://ws.soap.transfer.services.sedna.ser.com/"><dataHandler><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/></dataHandler></ns2:getContentObjectStreamResponse></soap:Body></soap:Envelope>
--uuid:6c8ac7c2-cac9-437f-a319-72c7c0e60328
Content-Type: */*
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

‰PNG
binary data
--uuid:6c8ac7c2-cac9-437f-a319-72c7c0e60328--

How can I parse just the binary part and get back the file?

Update 16.04.2019: I got the content with the following lines:

Dim rContent As New System.Text.RegularExpressions.Regex("(?<=Content-ID: <[^root].*[>])(.|\n)*(?=--uuid)")
Dim matchContent As Match = rContent.Match(documentResponse)
Dim documentContentData As String = matchContent.Value

But it seems that the String conversion messes up the binary encoding somehow. Writing that content to File with

Dim fileBytes As Byte() = UnicodeStringToBytes(trimmedContent)
File.WriteAllBytes("C:\Path\cloud.png", fileBytes)

Is bigger than the original file and in the wrong encoding.


Solution

  • I have found a solution which neither elegant nor recommendable. Parsing the response byte per byte and just copy the binary part by cutting the envelope and enclosing message (trial and error). Now let's just hope the endpoint never changes this format.

            Private Function getSoapFileBytes(url As String, endpoint As String, data As Byte()) As Byte()
                Dim result As String = ""
                Dim fileBytes As New List(Of Byte)
                Try
                    Dim req = WebRequest.Create(url)
                    req.Headers.Add("SOAPAction", url + endpoint)
    
                    req.ContentType = "application/soap+xml"
                    req.ContentLength = data.Length
                    req.Method = "POST"
    
                    Dim DataStream = req.GetRequestStream()
                    DataStream.Write(data, 0, data.Length)
                    DataStream.Close()
    
                    Dim WebResponse = req.GetResponse()
    
                    Dim resp = WebResponse.GetResponseStream()
    
                    Dim contentList As New List(Of Byte)
                    Dim ct As Byte() = New Byte() {}
    
                    Dim currentByte As Integer = 0
                    While currentByte > -1
                        currentByte = resp.ReadByte()
                        Dim myByte = BitConverter.GetBytes(currentByte)
                        ct.Concat(myByte)
                        contentList.Add(myByte.ElementAt(0))
                    End While
    
    
                    Dim fb As Byte() = New Byte() {}
    
                    For c As Integer = 772 To (contentList.Count - 49)
                        fileBytes.Add(contentList.ElementAt(c))
                    Next
    
                    DataStream.Close()
                    resp.Close()
                Catch ex As WebException
                    System.Diagnostics.Debug.WriteLine(ex.ToString())
                End Try
                System.Diagnostics.Debug.WriteLine(result)
                Return fileBytes.ToArray()
    
            End Function