Some application APIs expect requests to be submitted with the media type multipart/form-data. For example, the Jira Cloud platform REST API requires a file attachment to be uploaded as a POST request with multipart/form-data content.
In integrator.io, regardless of whether you are connecting to an HTTP- or REST-based application, you can upload content that requires multipart/form-data content using an HTTP import. That is, unlike an app-specific import, in which you must select a connector for that specific endpoint, in a universal HTTP import you can create or select a connection to any app – provided that it uses the HTTP or REST communication protocol.
Importing multipart/form-data content requires additional steps for you to specify the file or field to be synced, as described below.
A: Create an HTTP connection
- In Flow Builder, click Add destination/lookup.
- Select HTTP from the Application list.
- Continuing in the Create destination/lookup pane, select Transfer files into destination application to answer What would you like to do?
- If you have already created an HTTP connection to the destination application, and the Application details section of that connection are correctly configured for multipart/ form-data, you can procede to Create the transfer. Otherwise, click + to create your Connection.
- Enter a uniquely identifiable Name for the connection.
- Enter the Base URI.
- Use the drop-down list in the Media type field to select Multipart/form-data.
- Use the drop-down list for Override media type for success responses to select JSON.
- Use the drop-down list for Override media type for error responses to select JSON.
- In the Configure authentication section, enter the information for the platform you're transferring files to. For instructions on all possible authentication settings, see the HTTP section.
- Click Save & Close.
- With your new connection created, click Next.
B. Create the transfer
The new import opens in the Create transfer pane for you to customize its settings. At a minimum before saving, fill in the required fields:
- Name: a unique value by which you can identify this import later
- HTTP method: usually POST for a multipart/form-data HTTP import
In the section Where would you like the files transferred?, select POST for the HTTP method.
C. Build the request body
Click the pencil icon () next to the HTTP request body field to open the Build HTTP request body AFE.
The Build HTTP request body Advanced Field Editor opens for you to provide the body for the multipart/form-data request.
Enter your record into the Type your handlebars template here field. Part 1: JSON request body form contains the template you can use to create your data structure. Refer to your application’s API guide for the expected body request part.
- The multipart/form-data body can have only one file reference in each import.
- Do not include the boundary. integrator.io will automatically add it once the data is sent.
- The following example demonstrates the name attribute for each part.
Example: Send multipart/form-data in 2 parts
In the following example, you send JSON data to describe the file (part 1) and then the actual file is sent as binary data (part 2).
Example: Check out this QuickBooks example request body in practice. The only relevant part of the QuickBooks example is the section on Attaching a note to an object request body. All you need to do is configure the request body. integrator.io will handle the rest.
Part 1: JSON request body form
This is an example multipart/form-data body. It includes the name, value, and type of data. The value attribute is the object ID retrieved from a previous fetch. If you need to add a JSON object to the value field instead of a single value, you need to use: {{{jsonEncode (jsonSerialize field)}}}. For example, you need to add a JSON object to the value field if you’re using a handlebar to add the ID.
- The default encoding for "type": "inline" is UTF-8.
- If you use the optional filename field in the request body of a blob import, you must include the filename extension in the field value (example: "filename": "docName.json", "filename": "docName.csv", "filename": "docName.pdf", etc.)
[
{ // part 1 of multipart/form-data body
"name": <string>,
"value": <string>, // body of the part
"type": "inline||attachment", // default is "inline";
// "attachment" indicates "value" field contains a file
// reference handlebars string var., such as {{blob}}
"filename": <string>, // optional field (include extension if used in request body.)
"mime-headers": { // optional field
<header1 name - string>: <header1 value - string>,
<header2 name - string>: <header2 value - string>,
...
}
},
{ // part 2 of multipart/form-data body
...
},
...
]
If the API requires you to send additional fields along with the file in the form data, you can include these fields as name and value pairs as follows:
[ { "name":"file", "value":"{{blob}}" }, { "name":"customerName", "value":"John" }, { "name":"phone", "value":"123456789" } ]
Example "value" body (serialized)
"{\"AttachableRef\": [{\"EntityRef\": {\"type\": \"Bill\",\"value\": \"{{data._PARENT.Quickbooks_Bill_Id}}\"}}],\"ContentType\": \"image/jpg\",\"FileName\": \"{{split data.file '/' 5}}\"}"
Un-serialized data
{ "AttachableRef": [{ "EntityRef": { "type": "Bill", "value": "{{data._PARENT.Quickbooks_Bill_Id}}" } }], … }
Quickbooks bill attachment full example (Part 1 and 2)
Below is an example of a filled-in request body. This example sends a QuickBooks bill attachment. Note that because the "value" field used a JSON object instead of a single value, the data was serialized.
[ {// part 1 of multipart/form-data body "name": "file_metadata_0", "value": "{\"AttachableRef\": [{\"EntityRef\": {\"type\": \"Bill\",\"value\": \"{{data._PARENT.Quickbooks_Bill_Id}}\"}}],\"ContentType\": \"image/jpg\",\"FileName\": \"{{split data.file '/' 5}}\"}", // body of part 1 "type": "inline", "mime-headers": { // optional field "Content-Transfer-Encoding":"8bit", "content-type":"application/json; charset=UTF-8" } }, {// part 2 of multipart/form-data body "name":"file_content_0", "filename": "{{split data.file '/' 5}}", "type": "attachment", "mime-headers": { }, "value":"{{blob}}" } ]
Part 2: integrator.io processing and sending the data
After integrator.io processes the file, it configures and sends the data to the application. Do not include the boundary string since integrator.io adds that automatically. This configuration is not available in audit logs, so you won’t be able to see this version of the data. Below is an example of the processed and sent data:
--YOjcLaTlykb6OxfYJx4O07j1MweeMFem //boundary string Content-Disposition: form-data; name="file_metadata_01"; filename="attachment.json" Content-Type: application/json; charset=UTF-8 Content-Transfer-Encoding: 8bit { "AttachableRef": [ { "EntityRef": { "type": "Invoice", "value": "95" } } ], "FileName": "receipt_nov15.jpg", "ContentType": "image/jpg" } --YOjcLaTlykb6OxfYJx4O07j1MweeMFem //boundary string Content-Disposition: form-data; name="file_content_01"; filename="receipt_nov15.jpg" Content-Type: image/jpeg Content-Transfer-Encoding: base64 <insert base-64 encoded file content here> --YOjcLaTlykb6OxfYJx4O07j1MweeMFem-- //boundary string
Example: Send multipart/form-data for OpenAI
This example sends an HTML document to OpenAI. Note that because the value field used a JSON object instead of a single value, the data was serialized.
{ "name": "open ai file import", "_connectionId": "******", "ignoreExisting": false, "ignoreMissing": false, "oneToMany": false, "sandbox": false, "http": { "relativeURI": ["/files"], "method": ["POST"], "body": [ // part 1 of multipart/form-data body "[\n {\n \"name\": \"file\",\n \"value\": \"<!DOCTYPE html>\\n<html>\\n<head>\\n <title>Sample HTML Page<title>\\n<head>\\n<body>\\n <h1>Hello, World!</h1>\\n <p>This is a sample HTML page.</p>\\n</body>\\n</html>\",\n \"type\": \"inline\",\n \"mime-headers\": {\n \"Content-Disposition\": \"form-data\",\n \"content-type\": \"text/html\",\n \"filename\": \"My_File3\"\n }\n },\n {\n \"name\": \"purpose\", \n \"value\": \"assistants\", \n \"type\": \"inline\" \n }\n]" ], "headers": [ { "name": "content-type", "value": "multipart/form-data" } ], // part 2 of multipart/form-data body "batchSize": 1, "sendPostMappedData": true, "formType": "http" }, "adaptorType": "HTTPImport" }
D. Advanced settings
Add your blob key path in the advanced settings. When you use integrator.io to sync documents, attachments, images, etc. (i.e. raw blob data) you first need a blob export defined in your flow to get the raw blob data from an external application and into integrator.io storage. You then need to make sure that you have a response mapping on your blob export for the blobKey value that integrator.io returns whenever blob data is successfully stored in integrator.io. Assuming these two things have been done, use this field to indicate the JSON path where you mapped the blobKey value in your data, and then integrator.io will use the blobKey value to get the file out of integrator.io storage and transfer it to the import application.
E. Test your import
Finally, run the flow and test your import.
Example file upload: Jira Cloud platform
This tutorial imports an attachment per Jira’s requirements:
- This resource expects a multipart post....
- In order to protect against XSRF attacks, because this method accepts multipart/form-data, it has XSRF protection on it. This means you must submit a header of
X-Atlassian-Token: no-check
with the request, otherwise it will be blocked.- The name of the multipart/form-data parameter that contains attachments must be
"file"
.
It assumes that you have a working flow with the following configuration:
- A source application export flow step that stores the file to send to JIRA. (see Example file transfer: Salesforce to NetSuite)
- An HTTP import configured as previously described.
- A Jira Cloud platform connection set up with the Universal HTTP connector.
Use the following steps to set up your Jira import:
- Open the Edit Transfer page for the Jira import.
- Configure following settings:
- HTTP method: POST
- Relative URI: <existing path in your Jira app>
-
Configure HTTP headers:
X-Atlassian-Token
(name) andno-check
(value) - Override request media type: Do not override
- Click () to open the Build HTTP request body editor.
- Edit the body to include the variables for your file:
[
{
"name": "file",
"value": "{{blob}}",
"type": "attachment",
"filename":"upload_attachment {{timestamp}}"
}
] - Click Save, then from the Edit transfer page, expand the Advanced section.
- Enter the Blob key path for your file.
- Run the flow, and check your Jira account to verify the results.
See another example:
Comments
Quite helpful to understand multipart-form/data. Is an XML payload supported as well in the body?
Thanks for helping us to clarify and assist other readers, Bhushan Rane. Yes indeed, you may import XML-formatted records.
Hello Stephen,
I did the same but I got from integrator.io this error and I don't know why
Hi, Alaa Okby. I started a support ticket so that our team can try to look at the data you're submitting. (I'll keep an eye on it to see if anything in this article might have misled you.)
I would hope that the field editor might have alerted you to any JSON syntax errors, so there is probably an issue elsewhere in your flow – or perhaps something unique in your destination app's requirements.
actually, the error prevents me from saving the module so that is before running the flow.
We had a use case where there were additional attributes that needed to be sent along with the main attachment/blob, in this case we figured each unique attribute had to be a name value pair shown below.
[
{
"name": "UploadFile",
"value": "{{blob}}",
"type": "attachment"
},
{ "name": "signature", "value" : "{{{record.signatureOnly}}}"},
{ "name": "clientApp", "value" : "{{record.signatureData.0.clientApp}}"},
{ "name": "dbname", "value" : "{{record.signatureData.0.dbname}}"}
]
Hello Bhushan,
I tried it and it worked but what are the new attributes for? as I don't have these attributes in my record data.
Thanks
Hi All,
With {{blob}} , I believe is just the raw data of the file.
Can I just do {{base64Decode blob}} to encode it and upload it into our custom system?
What other attributes are available for us to use?
Cheers
J
Please sign in to leave a comment.