2

I am trying to use VBA to Post to an API. I have code that I've used in the past (with other APIs) whose structure and formatting has worked. But it didn't this time, it seems to be the Send command that is the culprit. So I searched the web and found a few different samples of how to format the Send and I've tried all of them, but none of them work.

The attached code sample includes several of the ways I've tried to format. I've commented out all but one but left the others in comments to show what I've tried. As you take a look at the code, know that I've tried every combination of commented out code that I could.

Each time, I get a server response that "No file uploaded or URL or base 64 provided."

However, if I put the same variables into Postman and send it from there, it works fine, so I know it is not an error on the API side, it's the way I'm formatting the VBA. I've checked the data many times to make sure there are no typos.

I would appreciate any suggestions.

    Sub macroPOST()
      Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
      Url = "https://api.ocr.space/parse/image"

       objHTTP.Open "POST", Url, False

      'objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
      objHTTP.setRequestHeader "apikey", "helloworld"
      objHTTP.setRequestHeader "Content-Type", "multipart/form-data"
      'objHTTP.setRequestHeader "Content-Type", "image/png"

      objHTTP.Send ("url=http://dl.a9t9.com/ocrbenchmark/eng.png&filetype=PNG&language=eng&isOverlayRequired=false&iscreatesearchablepdf=false&issearchablepdfhidetextlayer=false")
      'objHTTP.Send ("url=http://dl.a9t9.com/ocrbenchmark/eng.png")
      'objHTTP.Send ("url%3Dhttp%3A%2F%2Fdl%2Ea9t9%2Ecom%2Focrbenchmark%2Feng%2Epng")
      BodyContent = "{" & Chr(34) & "url" & Chr(34) & ":" & Chr(34) & "http://dl.a9t9.com/ocrbenchmark/eng.png" & Chr(34) & "}"
      'objHTTP.Send (BodyContent)

      replyTXT = objHTTP.responseText

      If objHTTP.Status = "200" Then 'success
        MsgBox replyTXT
      Else
        MsgBox ("Problem")
      End If
    End Sub
Swannekin
  • 53
  • 8
  • You shouldn't use `(`'s there. It's just `objHTTP.Send = "YourString"` (Disclaimer: I don't know if this will solve your problem in this case, but bracketing parameters passed to a procedure has meaning and is not harmless) – chris neilsen Aug 29 '19 at 05:08
  • I have not worked with this before but a quick search shows that [curl is smart enough to read the file and upload the contents with your request](https://stackoverflow.com/questions/35639646/no-file-uploaded-or-url-provided-when-calling-ocr-space-api). You will have to tweak it in your case. How? I am not sure. Do not have the time to test it. – Siddharth Rout Aug 29 '19 at 05:51

1 Answers1

0

You are very very close. It was just a matter of combining the correct headers and the correct format of the request's body.

It should look like that:

Option Explicit

Sub test()
Dim req As New WinHttpRequest 'add a reference to Microsoft WinHTTP Services version 5.1
Dim url As String
url = "https://api.ocr.space/parse/image"

With req
    .Open "POST", url, False
    .setRequestHeader "apikey", "helloworld"
    .setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    .send "url=http://dl.a9t9.com/ocrbenchmark/eng.png"
    Debug.Print .responseText
    Debug.Print .Status
End With
End Sub

And the response in JSON as follows:

{"ParsedResults":[{"TextOverlay":{"Lines":[],"HasOverlay":false,"Message":"Text overlay is not provided as it is not requested"},"TextOrientation":"0","FileParseExitCode":1,"ParsedText":"ELLIOT\r\n29 Comments f Facebook Twitter G* Google O Pinterest in LinkedIn 6 Reddit\r\nLockheed's I-J-2S spy planes are famously difficult to launch and land. Their extremely poor field of\r\nvision requires a chase car on the ground that can keep up with them.\r\nThey use some powerful vehicles and now we learn that the Air Force has turned to the all-electric\r\nTesla Model S to launch its own spy planes.\r\nWhile it is still being used today, the Lockheed IJ-2S\r\nwas designed in 1950S. It has always been an\r\nextremely difficult plane to operate and Mythbusters\r\neven suggested that it could be \"the most difficul\r\nplane to fly\" in the world.\r\nThey need a whole ground team to put i in the air and\r\nback on the ground.\r\nThe US Air Force used a Camaro Z/28, which\r\nJalopnik featured in an article 4 years ago:\r\ nbaaa.fun\r\nmemes, quizzes, inspiration\r\nHave fun now!\r\nbaaa.fun\r\n","ErrorMessage":"","ErrorDetails":""}],"OCRExitCode":1,"IsErroredOnProcessing":false,"ProcessingTimeInMilliseconds":"621","SearchablePDFURL":"Searchable PDF not generated as it was not requested."}

Now, if you need to include more of the optional parameters in your request you can structure its body like so:

.send "url=http://dl.a9t9.com/ocrbenchmark/eng.png&language=eng&isOverlayRequired=false&filetype=jpg&iscreatesearchablepdf=false&issearchablepdfhidetextlayer=false"

The parentheses issue that was referred in the comments, will not make a difference in this case, but nevertheless it is a valid point.

Stavros Jon
  • 1,695
  • 2
  • 7
  • 17
  • I must be getting close - the response you get is what I was expecting. But when I try the very code the you posted, after adding the reference to WinHTTP, I get this error: "Run-time error '-2147012894(80072ee2)' The operation timed out. Seems to be on the server end, so I will try again later today. Thank you for your suggestion! – Swannekin Aug 29 '19 at 15:13
  • @Swannekin BTW if you haven’t registered to get the free API key, the server blocks you for one day after sending 10 requests I think. – Stavros Jon Aug 29 '19 at 16:49
  • Comment Part 1: @Stavros Jon thank you very much, your suggestion worked perfectly, and I'm marking the question as answered. But that was just a test of the easiest method available, that of providing a URL. What I really have to do is to send an image file that is stored on a local machine to the API (which is an OCR function). Once again, everything that I tried failed, even though it works in Postman. I get the same error message of no file being uploaded. – Swannekin Aug 30 '19 at 01:29
  • Comment Part 2: The Send request that I used, parroting yours, is: .send "file=C:\Users\peter\Documents\image1.smalla.png&scale=true&language=eng&ocrEngine=2&isOverlayRequired=false&iscreatesearchablepdf=false&issearchablepdfhidetextlayer=false&istable=true" – Swannekin Aug 30 '19 at 01:30
  • Comment Part 3: When I look at the code that Postman generates it shows "name=\"file\"; filename=\"image1.smalla.png\" as the Key and value, and I'm not sure how to translate that extra nomenclature (3 things rather than 2) into the correct format. And I've tried it with full pathnames and just the filename. Any ideas? P.S. The API company is very nice but they claim no expertise in VBA so they can't provide any insights. – Swannekin Aug 30 '19 at 01:30
  • @Swannekin I have been blocked again because I was doing some tests. I will look into it once I'm unblocked. In the meantime, you can just upload your image in dropbox or google drive or something like that and just use the URL method. – Stavros Jon Aug 30 '19 at 10:05
  • Thanks so much for your help. I found a routine that handles sending a file in a post. I tested it and it works. This may help others with the same question that I had: http://www.ericphelps.com/scripting/samples/reference/web/http_post.txt Now the last phase of my quest, but I have my doubts - is it possible to achieve the same thing on a Mac. . . . . . . – Swannekin Aug 30 '19 at 13:10