Socket POST

I want to upload a file to a database. Is it possible to POST the file via HTTPSocket? If I try it with “SetFormData” I’ve got an error… any idea?

HTTPSocket.SetFormData(Dictionary)
HTTPSocket.POST(URL, timeout)

Best Regards
Sebastian

Unless you are using an old version of Xojo, you should use URLConnection instead.

Var mySocket As New URLConnection
Var file As FolderItem = SpecialFolder.Documents.Child("somefile.txt")
mySocket.Send("POST", "https://www.mydomain.com/endpoint", file)

AFAIK: To insert a file into a database you have to use a database connection - if you don’t have/use an API that performs that task for you.

It’s a REST API. To upload the data I have to configure some parameters and one is the “data” which is a file in json format. So therefore I tried it with “SetFormData” but there it’s not possible to define/insert a file…

Dim bForm as New Dictionary
bForm.Value(“id”) = “1234”
bForm.Value(“result”) = 'for this parameter a file in json format needs to be inserted

Socket.SetFormData(bForm)
data = Socket.POST(URL,5)

You will need to read the contents of the JSON file first before assigning it to bForm.Value("result")

If it doesn’t work you could try this:

Var socket As New URLConnection
Var jsonData As String = GenerateJSON(bForm)
socket.SetRequestContent(data, "application/json")

Var result As String
result = socket.SendSync("POST", URL,5)

Is the API public? Might help if I can read the docs.

This is not working because it expects a file…
I’ll try it…
Unfortunately not…

URLConnection.Send has two signatures, one requiring a FolderItem and another not:

I believe the second format requires first calling SetRequestContent passing your JSON string, as @Jeremie_L has posted.

If for some reason you must use the first signature, then you’d write the json string to a temporary text file and pass a FolderItem referencing that.

https://documentation.xojo.com/api/networking/urlconnection.html

URLConnection.Send with a FolderItem is for downloading to the FolderItem, it is unfortunately not an upload function. Sending a file as POST form data is possible, but we need to know the method the receiving API wants the file to provide any useful guidance.

1 Like

It’s probably expecting a multipart/form-data encoded HTTP form (the kind a browser would use to upload a file through a web form.) In which case, try this:

1 Like

Looking at the github repo. Couldn’t this code use a string array and Join / String.FromArray?

Dim bin as BinaryStream = BinaryStream.Open(FolderItem(mValues(i).ObjectValue))
		      
Dim s as String
		      
while not bin.EOF
	s = s + bin.Read(1024 * 16)
wend
		      
bin.Close()

I’m not sure how much appending to the string slows things down with smaller files, but couldn’t it have an impact with a large file?

Maybe something like this:

//danger - forum code. :) 
Dim bin as BinaryStream = BinaryStream.Open(FolderItem(mValues(i).ObjectValue))
		      
Dim s as String
Dim sa() as Strin
		      
while not bin.EOF
	sa.append(bin.Read(1024 * 16))

wend

s = String.FromArray(sa)
		      
bin.Close()

The original (and now obsolete/unsupported) code wrote the file data to a memory-backed BinaryStream for maximum efficiency:

Dim bs As BinaryStream = BinaryStream.Open(File)
out.Write(bs.Read(bs.Length) + CRLF) ' "out" is a BinaryStream backed by a MemoryBlock

Not sure why they changed it, and not sure whether your proposed change would have a significant performance impact one way or the other.

Thanks to all for the help for now. I’ll check it after my vacation…
I have some more infos maybe this helps:

curl -X 'POST' \
  'URL' \
  -H 'accept: application/json' \
  -H 'Content-Type: multipart/form-data' \
  -F 'id=1234' \
  -F 'result=@data.json;type=application/json'

Well it certainly looks like you need multipart/form-data, so you should check out the class Andrew linked :slight_smile:

1 Like

Rough translation using the linked class:

Dim f as FolderItem = GetOpenFolderItem("*.*")

Dim uc as URLConnection = new URLConnection()
uc.RequestHeader("Accept") = "application/json"
uc.RequestHeader("Content-Type") = "multipart/form-data"  

Dim multipartContent as MultipartFormDataContent = new MultipartFormDataContent()
multipartContent.Add("id","1234")
multipartContent.Add("result",f)

multipartContent.SetURLConnectionMultipartContent(uc)

Dim result as String = uc.SendSync("POST", "URL")

Thanks.

URLConnection

is not working. I don’t get any result/response, the file or string is always empty. Any idea?