How does one create an http post call with Excel VBA?

3.5k views Asked by At

I am able to do GET's with ease by calling the following code:

Dim theURL As String, theRequest As Object
theURL = "http://localhost/myapp/encrypt.jsp?str=" & _
    encodeStr(range("I10").Value) & "&user=myUser&pass=myPass"
Set theRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
theRequest.Open "GET", theURL 
theRequest.Send
MsgBox theRequest.ResponseText

However I am having significantly more trouble with a post. The html of the form which I am trying to simulate is:

<form method="post" enctype="multipart/form-data" action="managefile?operation=upload">
  <table>
    <tr>
        <h3 align="center">Upload File</h3>
    </tr>
    <tr>
        <td>File:</td>
        <td><input type="file" size="80" name="fname"></td>
        <td><input type="Submit" value="Upload"></td>
    </tr>
  </table>
</form>

The get API's generally expect the username and password to be passed as parameters. Since I don't think I can pass a POST with parameters I have tried sending the post with data split by boundaries using techniques I've found on various pages (including here). None of these have worked.

Here is an example of some code I tried which did not work:

Dim theURL As String, theRequest As Object, theBody As String, theBoundary As String
theBoundary = "-----------------13850284693" ' Sample, generating from timestamp        
theBody = theBoundary & vbCrLf
theBody = theBody & "Content-Disposition: form-data" & vbCrLf & vbCrLf
theBody = theBody & "user=myUser&pass=MyPass" & vbCrLf ' I am wondering if this also needs to include action
theBody = theBody & theBoundary & vbCrLf
theBody = theBody & "Content-Disposition: form-data; name=""fname""; filename=""update.xml""" & vbCrLf
theBody = theBody & "Content-Type: text/xml" & vbCrLf & vbCrLf
theBody = theBody & "<MyXML><Node1>ff</Node1></MyXML>"
theBody = theBody & vbCrLf
theBody = theBody & theBoundary & "--" & vbCrLf

theURL = "http://localhost/myapp/managefile?operation=upload"
Set theRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
theRequest.Open "POST", theURL, False
theRequest.setRequestHeader "Cache-Control", "no-cache"
theRequest.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & theBoundary
theRequest.setRequestHeader "Content-Length", Len(theBody)    
theRequest.Send theBody

The page I get back from this example is that I am not logged in, so it seems it is not passing my parameters properly.

I've also tried passing the username and password as part of the URL, e.g.

theURL = "http://localhost/myapp/managefile?operation=upload&user=myUser&pass=myPass"

And from this I get an error saying it (the API) expects

<MyXML>...</MyXML>

and it is getting:

-----------------13850284693..(continues)..<MyXML><Node1>ff</Node1></MyXML>.

This leads me to believe that it is logging in fine but not doing the post properly.

I tried doing the same thing and just sending the XML but this also didn't work. This wouldn't make sense to me to work since the API would not know which parameter to associate the XML to.

The last thing I tried was running a simple get which logs the user in and returns the cookie and then passes this back. This seemed to do the same thing as above, still have a problem with the POST.

Here is my try setting the cookie. It appears to work the same as when I pass the parameters -- it looks like login works but it fails to do the post correctly (specifically the xml I am trying to send):

Dim theLoginRequest, thePostRequest
Set theLoginRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
theLoginRequest.Open "GET", "localhost/myapp/login?user=myUser&pass=myPass"
theLoginRequest.Send
Set thePostRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
thePostRequest.Open "POST, "<post request>", False
thePostRequest.setRequestHeader "Cookie", theLoginRequest.getResponseHeader("Set-Cookie")

...etc.


The string that I have in there is identical to the content of the file that I am able to upload to the form without a problem.

Any ideas?

1

There are 1 answers

2
Tom Robinson On

The site uses a cookie-based login. So you need to log in with GET, pick up the returned cookie, then include that same cookie in the headers of the POST request.