How to make a POST request with multipart/form-data using HTTP Task?

Hi,

I want to send a multipart/form-data POST request to an external endpoint from Flowable using HTTP Task, specifically, to upload a file and some form fields.

After a lot of searches and attempts, I still have no idea how to achieve this. What should I put in the Request Body of the HTTP Task?

Thank you for your help.

I don’t think the default http task can send multipart, because it would need to chunk the parts instead of passing the body. One way - maybe, as I haven’t tested or checked this - is to use a service bean that is called in the body expression that would generate the correct multipart body.

Hey.

Maybe you can use “Script task” with “Groovy” to achieve something like this below. You would obviously need to tweak the file reading and other sendings, but this should be general solution. With this request, I was able to send JSON data and file.

import javax.net.ssl.*
import java.io.*

final def boundary =  'abcd' + Long.toString(System.currentTimeMillis()) * 2 + 'dcba'
final def twoHyphens = '--'
final def lineEnd = '\r\n'
final def hash = 'test'

try 
{
	def file = new File(fileLoc);
	if(!file.exists() || file.isDirectory()) 
	{
		println "[ERROR] Invalid file"
		return
	}

	def fileInputStream = new FileInputStream(file);
	def json = '{"path":"' + file.getName() + '","contentHash":"SHA-256{' + hash +'}","version":"' + version + '","type":"REGULAR","length":"' + file.length() + '"}'

	def connection = new URL(url).openConnection() as HttpsURLConnection
	connection.setDoInput(true)
	connection.setDoOutput(true)
	connection.setUseCaches(false)
	connection.setRequestMethod('POST')
	connection.setRequestProperty('Connection', 'Keep-Alive');
	connection.setRequestProperty('Authorization', 'Basic ' + auth)
	connection.setRequestProperty('Content-Type' , 'multipart/form-data; boundary=' + boundary)
	def outputStream = new DataOutputStream(connection.getOutputStream())

	outputStream.writeBytes(twoHyphens + boundary + lineEnd);
	outputStream.writeBytes('Content-Disposition: form-data; name="component"' + lineEnd)
	outputStream.writeBytes('Content-Type: text/plain; charset=UTF-8' + lineEnd)
	outputStream.writeBytes('Content-Transfer-Encoding: 8bit' + lineEnd)
	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(component)

	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(twoHyphens + boundary + lineEnd)
	outputStream.writeBytes('Content-Disposition: form-data; name="version"' + lineEnd)
	outputStream.writeBytes('Content-Type: text/plain; charset=UTF-8' + lineEnd)
	outputStream.writeBytes('Content-Transfer-Encoding: 8bit' + lineEnd)
	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(version)

	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(twoHyphens + boundary + lineEnd)
	outputStream.writeBytes('Content-Disposition: form-data; name="entryMetadata"' + lineEnd)
	outputStream.writeBytes('Content-Type: text/plain; charset=UTF-8' + lineEnd)
	outputStream.writeBytes('Content-Transfer-Encoding: 8bit' + lineEnd)
	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(json)

	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(twoHyphens + boundary + lineEnd)
	outputStream.writeBytes('Content-Disposition: form-data; name="entryContent-' + hash + '"; filename="' + file.getName() + '"' + lineEnd)
	outputStream.writeBytes('Content-Type: application/octet-stream' + lineEnd)
	outputStream.writeBytes('Content-Transfer-Encoding: binary' + lineEnd)
	outputStream.writeBytes(lineEnd)

	def maxBufferSize = 1 * 1024 * 1024
	def bytesAvailable = fileInputStream.available()
	def bufferSize = Math.min(bytesAvailable, maxBufferSize)
	def buffer = new byte[bufferSize]
	def bytesRead = fileInputStream.read(buffer, 0, bufferSize)
	while(bytesRead > 0) 
	{
		outputStream.write(buffer, 0, bufferSize)
		bytesAvailable = fileInputStream.available()
		bufferSize = Math.min(bytesAvailable, maxBufferSize)
		bytesRead = fileInputStream.read(buffer, 0, bufferSize)
	}

	outputStream.writeBytes(lineEnd)
	outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd)
	fileInputStream.close()
	outputStream.flush()
	outputStream.close()
	def rc = connection.responseCode
	if (rc == 204) 
	{
		println '[SUCCESS] Upload completed'
	}
	else 
	{
		println "[ERROR] Wrong response code: ${rc}"
	}
}
catch(Exception ex) 
{
    println ex.toString()
}

Hi,

@tdoan Did you implement one of the 2 solutions proposed (by @joram or by @fiki574 ?)
I also need to use a multipart request, and I wanted to know if you have any feedback on this ?

Thank you.