I'm running into this problem, as well. It seems to be limited to the WinHttp.WinHttpRequest
COM interface. There are a couple of different options to resolve this.
After some digging, I found this post from a Microsoft employee. It gives a clear explanation and recommends sending in a binary array.
If you are POSTing a string using the WinHttpRequest object, you cannot
override how it encodes the string for transmission. The WinHttpRequest
object will always convert the Unicode string to UTF-8.
However, note that a Unicode string that contains only 7-bit
LATIN-1/ISO-8859-1 characters will remain unchanged when encoded as UTF-8
;-) In such cases, the WinHttpRequest object does not append a
"Charset=UTF-8" attribute to your Content-Type header. (And I would think
that the server would assume that the POST data is ISO-8859-1.)
So, if the XML text data that you are POSTing contains LATIN-1 alphanumeric
or punctuation character codes (each less than decimal 128), then all you
should have to do is specify the "ISO-8859-1" charset in your Content-Type
header:
WinHttpReq.SetRequestHeader "Content-Type", "application/xml;Charset=ISO-8859-1"
However, if your POST data contains 8-bit characters, then you cannot supply
the data as a string to the Send method. In order to avoid the UTF-8
conversion, your application must convert the string into a byte array, and
supply that instead. The WinHttpRequest object will not attempt any data
conversion on a byte array.
Regards,
Stephen Sulzer
Microsoft Corporation
A second option, other than sending in a binary array, is to switch to Msxml2.XMLHTTP
or Msxml2.ServerXMLHTTP
. Neither of these mangle the Content-Type
header. Luckily, when WinHttp.WinHttpRequest
was created, Microsoft intentionally used Msxml2.XMLHTTP
as a template for the interface. So, it is fairly trivial to convert the code.
Also, the Msxml2.ServerXMLHTTP
COM interface uses WinHTTP internally. So, while you are losing access to some of the features that are exclusive to WinHttp.WinHttpRequest
, both use the same backend.
The third option is to use ADODB.Stream
. It allows you to work with an IStream
, which isn't something you can normally do from VBA. The sample code below is based on the answer on the question "How to create 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)
Content-Type
string? – Discretionary