I am also facing this problem. It seems to be limited by the WinHttp.WinHttpRequest
COM WinHttp.WinHttpRequest
. There are several different solutions to this problem.
After some digging, I found this post from a Microsoft employee. It gives a clear explanation and recommends sending to a binary array.
If you use a POSTing string using the WinHttpRequest object, you cannot override how it encodes the string for transmission. A WinHttpRequest object will always convert a Unicode string to UTF-8.
However, note that a Unicode string containing only 7-bit LATIN-1 / ISO-8859-1 characters remains unchanged when encoded as UTF-8 ;-) In such cases, the WinHttpRequest object does not add the attribute "Charset = UTF-8" for your Content-Type header. (And I would think the server would assume that the POST data is ISO-8859-1.)
So, if the XML text data that you use POST contains LATIN-1 alphanumeric or punctuation marks (each is less than the decimal number 128), then all you need to be to specify the encoding "ISO-8859-1" in your Content -Type header:
WinHttpReq.SetRequestHeader "Content-Type", "application/xml;Charset=ISO-8859-1"
However, if your POST data contains 8-bit characters, you cannot provide data as a string for the send method. To avoid UTF-8 conversions, your application should convert the string to an array of bytes and put this instead. The WinHttpRequest object will not attempt to perform any data conversion into an array of bytes.
Hello,
Stephen Sulzer
Microsoft Corporation
The second option, in addition to sending in a binary array, is to switch to Msxml2.XMLHTTP
or Msxml2.ServerXMLHTTP
. None of them control the Content-Type
header. Fortunately, when WinHttp.WinHttpRequest
was created, Microsoft intentionally used Msxml2.XMLHTTP
as a template for the interface. Thus, it is quite simple to convert the code.
In addition, the Msxml2.ServerXMLHTTP
COM interface uses WinHTTP internally . Thus, while you lose access to some functions that are exclusive to WinHttp.WinHttpRequest
, both use the same backend.
The third option - to use ADODB.Stream
. This allows you to work with IStream
, which you usually cannot do with VBA. The code sample below is based on the answer to the question How to create a BinaryArray in VbScript? .
' Create a Binary Stream Set objStreamBinary = CreateObject("ADODB.Stream") objStreamBinary.Type = 1 objStreamBinary.Open ' Create a Text Stream Set objStreamText = CreateObject("ADODB.Stream") objStreamText.Type = 2 objStreamText.Open ' Copy the POST data to the Text Stream objStreamText.WriteText strRequest objStreamText.Position = 2 ' Copy the Text Stream Contents to the Binary Stream objStreamText.CopyTo objStreamBinary objStreamText.Close ' Read the contents of the Binary Stream ' and send it to the WinHttpRequest object web_Http.Send objStreamBinary.Read(-1)