Support Questions

Find answers, ask questions, and share your expertise

How to send an http POST multipart/form-data request with a file attached using Apache-nifi's InvokeHttp processor?

avatar
New Contributor

I am trying to send a multipart/form-data request to a POST API using Nifi's InvokeHTTP processor. This request takes a json and a file. The request headers and request body in POSTMAN look something like this -


POST /delivery/deliverPackage
User-Agent: PostmanRuntime/7.6.1
Accept: */*
Host: example.hostname:port
accept-encoding: gzip, deflate
content-type: multipart/form-data; boundary=--------------------------161413078116998145311888
content-length: 1115
json={ "destinationProtocol" : "HL7", "destinationFormat": "HL7_V2_ORU", "destinationType": "example", "destinationConnectionParams":{ "URI": "example", "HOST": "example", "PORT": "example" } }file=[object Object]


where the file object contains the file details I am trying to send.


I want to send this multipart/form-data request in nifi. Based on an answer I saw on one of the forums (sorry do not have the link to it), I am trying to create this request body in the content of the flowfile using ReplaceText processor before sending the flowfile to an InvokeHttp processor. The flowfile content looks something like this -


POST /delivery/deliverPackage
User-Agent: curl/7.46.0
Accept: */*
Host: example.hostname:port
accept-encoding: gzip, deflate
content-type: multipart/form-data; boundary=--------------------------161413078116998145311888
content-length: 1115

--------------------------161413078116998145311888
Content-Disposition: form-data; json="{ "destinationProtocol" : "HL7", "destinationFormat": "HL7_V2_ORU", "destinationType": "example", "destinationConnectionParams":{ "URI": "example", "HOST": "example", "PORT": "example" } }"

anonymous
--------------------------161413078116998145311888
Content-Disposition: form-data; name="file"; filename="/path/to/file/in/localsystem.HL7”
Content-Type: text/plain

contents of the file
--------------------------161413078116998145311888--


This doesn't seem to be working though, it doesn't look right to me. I am pretty new to Nifi. Can anyone help me understand what I'm doing wrong or give some insights on how to handle this properly? Thanks!


I have instead tried to use an ExecuteStreamCommand processor to simply run the curl command with command arguments -


-X POST;"https://example.hostname:port/delivery/deliverPackage?json=%7B%20%22destinationProtocol%22%20%3A%20%22HL7%22%2C%20%22destinationFormat%22%3A%20%22HL7_V2_ORU%22%2C%20%22destinationType%22%3A%20%22example%22%2C%20%22destinationConnectionParams%22%3A%7B%20%22URI%22%3A%20%22example%3A%2F%2Fexample%3A15050%22%2C%20%22HOST%22%3A%20%22example%22%2C%20%22PORT%22%3A%20%22example%22%20%7D%20%7D";-H "Content-Type: multipart/form-data";-F "file=@/path/to/file/in/localsystem.HL7";


This works, but I wanted to know how to do it using the InvokeHttp processor. Any help is greatly appreciated! Thank you.


10 REPLIES 10

avatar
New Contributor

Has anyone been successful yet with POST multipart via invokehttp? [We are running 1.9.2.]

avatar
Master Collaborator

Hi @ankita_pise , 

Were you able to achieve this using InvokeHttp processor ?

I am also looking for the solution.

 

Thanks,

Mahendra

avatar
Explorer

Add me to this growing list.

avatar
Explorer

Any luck on this?

i am trying to POST multiple files to API

curl -X POST "https://xxxxxx/xxxxx" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file1=@File1.csv;type=application/vnd.ms-excel" -F "file2=@File2.txt;type=text/plain" -F "file3=@File3.csv;type=application/vnd.ms-excel" -F "format=flat"

avatar
Super Guru

@ankita_pise Did you try appending the json string of values to the Url and like you did in curl?  

I believe this may work if it works in Curl.

 

Let us know the results.

avatar
New Contributor

Anyone having the solution for this we are struggling lot many days!!!

 

We need to send file in multi-part/formdata...

avatar
Master Collaborator

I could not succeed in multipart upload with InvokeHTTP processor.
So I used a simple java code to upload file using 'multipart/form-data'.
Invoked java code from nifi SprintContextProcessor.
As my file was large, I wrote the file content to disc before invoking 'SprintContextProcessor' and using java code read the file content and uploaded to the target.

You can transfer flow file content directly to the java code (SpringContext processor).

 

Thanks

Mahendra

avatar
New Contributor

@hegdemahendra i were able to generate dynamic multipart payload via below groovy script

 

 


@hegdemahendra wrote:

I could not succeed in multipart upload with InvokeHTTP processor.
So I used a simple java code to upload file using 'multipart/form-data'.
Invoked java code from nifi SprintContextProcessor.
As my file was large, I wrote the file content to disc before invoking 'SprintContextProcessor' and using java code read the file content and uploaded to the target.

You can transfer flow file content directly to the java code (SpringContext processor).

 

Thanks

Mahendra


import groovy.json.JsonSlurper
@Grab("org.apache.httpcomponents:httpmime:4.3.6")
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.entity.mime.content.StringBody
import org.apache.nifi.processor.io.InputStreamCallback
import org.apache.nifi.processor.io.OutputStreamCallback

MultipartEntityBuilder multipartRequestEntity = new MultipartEntityBuilder()
multipartRequestEntity.addPart('id', new StringBody("id"))
multipartRequestEntity.addPart('version', new StringBody("version"))
//
//

def slurper = new JsonSlurper();
resp = multipartRequestEntity.build()

flowFile = session.get()

session.read(flowFile, { inputStream ->
    jsonInput = slurper.parse(inputStream);
} as InputStreamCallback)


flowFile = session.write(flowFile, {
    outputStream -> resp.writeTo(outputStream);
} as OutputStreamCallback)
flowFile = session.putAttribute(flowFile, "mime.type", resp.getContentType().getValue())
flowFile = session.putAttribute(flowFile, "Content-Type", resp.getContentType().getValue())
session.transfer(flowFile, REL_SUCCESS)

 https://gist.github.com/cedric05/b3c77809ecf6e566593e3af599edee5f

connect this to invokehttp processor. you will be able to make multipart http request.

 

above script should be used incase of dynamic multipart, for static use invokehttp directly with 

properties
`post:form:key`: `<data>`

 

avatar
Master Mentor

@ankita_pise 

Have you tried using the "PostHttp" [1] processor instead to send your multi-part form data content FlowFile?

It would be configured as follows:

MattWho_0-1621545997014.png

[1] https://nifi.apache.org/docs/nifi-docs/components/org.apache.nifi/nifi-standard-nar/1.13.2/org.apach...

 

If you found this helped with yoru query, please take a moment to login and click accept on this solution,
Thank you,

Matt