File upload with URLConnection - InvalidArgumentException?

I am trying to upload a PDF file to an API endpoint and Im getting this InvalidArgumentException. Can anyone help me figure out what Ive got wrong here?

Self.ClearRequestHeaders
var pdfstream As TextInputStream
var pdfstring as string
Try
  pdfstream = TextInputStream.Open(pdffile)
  pdfstream.Encoding = Encodings.MacRoman
  pdfstring = pdfstream.ReadAll
Catch e As IOException
  MessageBox("Error accessing file.")
End Try
pdfstream.Close

Self.RequestHeader("Content-Type") = "multipart/form-data"
Self.RequestHeader("Authorization") = "Bearer "+ myAPI.apitoken
var payload as string ="https://myAPI.com/api/v1/quickAdd?quoteID=" + id +_
"&itemID=null&machine=BigMachine&material=pick%material&thicknes=.125&thickness_Units=inch&qty=100&units=inch"
Self.SetRequestContent(pdfstring, "multipart/form-data")
Self.Send("POST", payload)

What is the value of “id”? If it contains something not suited for a URL you can get a InvalidArgumentException from that.

Its always some string like this that I get back from the call that preceeds this one:
054544e4-972e-425a-a877-dca3ba63bc4d

I see ClearRequestHeaders, are you re-using a socket? Try creating a new URLConnection for subsequent requests. Re-using a socket can lead to inexplicable problems so myself and some other people I respect recommend against doing so.

Thanks Tim, Its a new URLConnection - thats just in there out of habit (I will stop doing that, thx)

It could also be the way you’re setting multipart/form-data but it’s not actually formatted that way.

(this is really had to debug without code / access to the request that’s failing)

Im trying to find examples of properly formatted multipart/form data. The API doc has the CURL that works:

curl -X POST --header 'Content-Type: multipart/form-data' --header 'Accept: application/json' {"type":"formData"} 'https://myAPI.com/api/v1/quoteOnline/quickAddCAD?quoteID=054544e4-972e-425a-a877-dca3ba63bc4d&itemID=null&machine=Kongsberg&material=32%20ECT%20B&thickness=.125&thickness_Units=inch&qty=1000&units=inch'

but I dont see any examples of how to format the file attachment. The API “try it out” just has a button to attach the file to the call at the bottom of the list of values in those key/val pairs. I am not getting the call to go out at all, its erroring in xojo.

Does the API accept another type of format? You have to construct multipart/form-data yourself in Xojo. I don’t have anything handy, but I know something exists… somewhere…

URLConnection does some validation before it makes an outbound request. Sometimes if the framework knows that it can’t form a valid request you get an exception.

Thanks Tim. I am researching how to form this. I cant believe its that obscure or difficult…

I have some old code for the HTTPSocket class. Needs to be updated for URLConnection, but it’s a place to start.

2 Likes

Wow Andrew, thank you! I did run accross this in a post but I was thnking it must be part of something more complicated than I want to do but I am begining to see it is either this approach or Christian’s cURL classes.

I also have an open source libcurl wrapper for Xojo :slight_smile:

1 Like

It’s most likely the % in the value for material:

material=pick%material

% is used for encoding characters in urls and your probably need to encode that value.

For each value (not the keys or the =) try encoding it with EncodeUrlComponent

2 Likes

Thanks Greg. I did catch that % should have been %20 but encoding all the values seems to have it working, Im not sure what the culprit was but those values will be fed by some other ui so I appreciate the solution. @Andrew_Lambert I did also use your old code and it was very minor to change - thank you immensly for that! I think all that had to be done was to change the httpsocket to a URLConnection.