Include attachment using POST method

I am working on a FreshDesk integration where once the user clicks “Send”, I attempt to create a FreshDesk ticket via their API (https://developers.freshdesk.com/api/#create_ticket). I can create a ticket just fine using

[code] Dim response, reqMethod As String
Dim HTTPSFreshDesk As new HTTPSecureSocket
Dim requestURL As String = “https://{domain}.freshdesk.com/api/v2/” + request

HTTPSFreshDesk.Secure = True
HTTPSFreshDesk.SetRequestContent(value, “application/json”)
HTTPSFreshDesk.SetRequestHeader(“Authorization”, “Basic [token]”)
HTTPSFreshDesk.RequestHeaders.AppendHeader(“Content-Type”, “application/json”)
HTTPSFreshDesk.Yield = True
HTTPSFreshDesk.ConnectionType = SSLSocket.SSLv23

Select Case httpMethod
Case enumHTTPMethods.POST
reqMethod = “POST”

Case enumHTTPMethods.DELETE
reqMethod = “DELETE”

Case else
Return “{}”

End Select

response = HTTPSFreshDesk.SendRequest(reqMethod, requestURL, 5)

Return response
[/code]

The problem comes when I include an attachment using

[code] Dim response, reqMethod As String
Dim HTTPSFreshDesk As new HTTPSecureSocket
Dim requestURL As String = “https://{domain}.freshdesk.com/api/v2/” + request

Dim Boundary As String
Static CRLF As String = EndOfLine.Windows
Dim data As New MemoryBlock(0)
Dim out As New BinaryStream(data)

Boundary = “–” + Right(EncodeHex(MD5(Str(Microseconds))), 24) + “-bOuNdArY”

For Each key As String In d.Keys
out.Write(“–” + Boundary + CRLF)
If VarType(d.Value(Key)) = Variant.TypeString Then
out.Write(“Content-Disposition: form-data; name=”“” + key + “”“” + CRLF + CRLF)
out.Write(d.Value(key) + CRLF)
ElseIf d.Value(Key) IsA FolderItem Then
Dim file As FolderItem = d.Value(key)
out.Write(“Content-Disposition: form-data; name=”“” + key + “”“; filename=”“” + File.Name + “”“” + CRLF)
out.Write(“Content-Type: application/json” + CRLF + CRLF) ’ replace with actual MIME Type
Dim bs As BinaryStream = BinaryStream.Open(File)
out.Write(bs.Read(bs.Length) + CRLF)
bs.Close
End If
Next
out.Write(“–” + Boundary + “–” + CRLF)
out.Close

HTTPSFreshDesk.Secure = True
HTTPSFreshDesk.Yield = True
HTTPSFreshDesk.ConnectionType = SSLSocket.SSLv23
HTTPSFreshDesk.SetRequestHeader(“Authorization”, “Basic [token]”)
HTTPSFreshDesk.RequestHeaders.AppendHeader(“Content-Type”, “multipart/form-data”)
HTTPSFreshDesk.SetRequestContent(data, “multipart/form-data; boundary=” + Boundary)
'HTTPSFreshDesk.SetRequestContent(value, “application/json”)
'HTTPSFreshDesk.RequestHeaders.AppendHeader(“Content-Type”, “application/json”)

Select Case httpMethod
Case enumHTTPMethods.POST
reqMethod = “POST”

Case enumHTTPMethods.DELETE
reqMethod = “DELETE”

Case else
Return “{}”

End Select

response = HTTPSFreshDesk.SendRequest(reqMethod, requestURL, 5)

Return response[/code]

Yet cURL works perfectly…

curl -v -u {username}:{password} -F "attachments[]=@/home/administrator/up.csv" -F "email=me@example.com" -F "subject=Ticket Title" -F "description=this is a sample ticket" -F "status=2" -F "priority=1" -X POST 'https://{domain}.freshdesk.com/api/v2/tickets'

Thoughts?

Have you tried a new framework socket?

I haven’t. I’ll have to play around with it. Would I still need to generate the multi-part myself?

The problem here is that FreshDesk wants the entire submission in a JSON string (including the attachment, I assume). It does not like form fields.

Honestly it’s just a wild stab in the dark. I much prefer the simplicity of the classic framework, but the new HTTP Socket is so much more up-to-date that it’s worth the time to deal with.

Judging from the curl command line you posted, I believe that the API is expecting the attachments to be in a nested multipart form field. In other words, an array of one or more files encoded in a single form element instead of one for each file. The multipart form generator code you’re using doesn’t support that.

e.g. add a new section to the form generator code to handle an array of FolderItems (untested!):

[code] For Each key As String In d.Keys
out.Write("–" + Boundary + CRLF)
If VarType(d.Value(Key)) = Variant.TypeString Then
out.Write(“Content-Disposition: form-data; name=”"" + key + “”"" + CRLF + CRLF)
out.Write(d.Value(key) + CRLF)
ElseIf d.Value(Key) IsA FolderItem Then
Dim file As FolderItem = d.Value(key)
out.Write(“Content-Disposition: form-data; name=”"" + key + “”"; filename=""" + File.Name + “”"" + CRLF)
out.Write(“Content-Type: application/json” + CRLF + CRLF) ’ replace with actual MIME Type
Dim bs As BinaryStream = BinaryStream.Open(File)
out.Write(bs.Read(bs.Length) + CRLF)
bs.Close

//BEGIN NEW CODE  
ElseIf VarType(FormData.Value(Key)) >= Variant.TypeArray Then  ' attachments
  Dim files() As FolderItem = FormData.Value(key)
  Dim subboundary As String = "--" + Right(EncodeHex(MD5(Boundary)), 24) + "-bOuNdArY"
  out.Write("Content-Disposition: form-data; name=""" + key + """" + CRLF)
  out.Write("Content-Type: multipart/mixed; boundary=" + subboundary  + CRLF + CRLF)
  For Each f As FolderItem In files
    out.Write("--" + subboundary + CRLF)
    out.Write("Content-Disposition: attachment; filename=""" + f.Name + """" + CRLF)
    out.Write("Content-Type: application/octet-stream" + CRLF + CRLF) ' replace with actual MIME Type
    Dim bs As BinaryStream = BinaryStream.Open(f)
    out.Write(bs.Read(bs.Length) + CRLF)
    bs.Close
  Next
  out.Write("--" + subboundary + "--" + CRLF)
//END NEW CODE

End If

Next
out.Write("–" + Boundary + “–” + CRLF)
out.Close[/code]

You may want to use CURL functions in MBS CURL Plugin.
The FormAdd functions allow you to build a multi value form data and send it.
This includes multiple attachments.