3

I'm trying to send a multipart request with the following form-data:

------WebKitFormBoundaryjFqPRXY6RQpdTRvE
Content-Disposition: form-data; name="file"; filename="Sample.csv"
Content-Type: application/vnd.ms-excel


------WebKitFormBoundaryjFqPRXY6RQpdTRvE
Content-Disposition: form-data; name="data"; filename="blob"
Content-Type: application/json

{"name":"Sample5","type":"Csv","firstRowIsHeader":true,"columns":[{ ... }]}
------WebKitFormBoundaryjFqPRXY6RQpdTRvE--

The above data is normally being created and sent by a web service.
I'm trying to replicate the exact same HTTP request from Node-RED.
JSON data is already prepared so it's just creation of the multipart request.

I've tried using node-red-contrib-http-multipart but I'm not really sure how to configure it.

[{"id":"e0fde1bd.e0aa","type":"httpInMultipart","z":"fc689d44.1c52","name":"","url":"/test/upload","method":"post","fields":"[ { \"name\": \"file\", \"maxCount\": 1}, { \"name\": \"data\", \"maxCount\": 1} ]","swaggerDoc":"","x":1390,"y":820,"wires":[["d109ed84.14d1d","8a39aaa0.6934c8","d0bc5b20.45f3a8"]]},{"id":"a2318dfd.bae7d","type":"http in","z":"fc689d44.1c52","name":"","url":"/test/send","method":"get","upload":false,"swaggerDoc":"","x":1380,"y":680,"wires":[["d7cfc418.89eb98"]]},{"id":"14c992f3.8652ad","type":"http response","z":"fc689d44.1c52","name":"","x":1750,"y":680,"wires":[]},{"id":"d109ed84.14d1d","type":"debug","z":"fc689d44.1c52","name":"","active":true,"console":"false","complete":"true","x":1570,"y":780,"wires":[]},{"id":"8a39aaa0.6934c8","type":"http response","z":"fc689d44.1c52","name":"","statusCode":"","headers":{},"x":1570,"y":860,"wires":[]},{"id":"1a646c83.8da7d3","type":"debug","z":"fc689d44.1c52","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1790,"y":780,"wires":[]},{"id":"d7cfc418.89eb98","type":"template","z":"fc689d44.1c52","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<form action=\"/test/upload\" method=\"POST\" enctype=\"multipart/form-data\">\n  <div>\n    <input type=\"file\" name=\"file\">\n    <input type=\"submit\" value=\"Submit\">\n  </div>\n</form>","output":"str","x":1580,"y":680,"wires":[["2971b104.12737e","14c992f3.8652ad"]]},{"id":"d0bc5b20.45f3a8","type":"change","z":"fc689d44.1c52","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t   \"file\": req.files.file[0].buffer,\t   \"data\": \"test\"\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1620,"y":820,"wires":[["1a646c83.8da7d3"]]},{"id":"2971b104.12737e","type":"debug","z":"fc689d44.1c52","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1730,"y":640,"wires":[]}]

Any kind of pointers on how to tackle the problem would be greatly appreciated.

libzz
  • 589
  • 2
  • 10
  • 29

2 Answers2

2

You don't need the multipart contribution node any more. For a while now the out of the box http input node has been able to handle multipart file uploads.

Set the method to POST and check the file uploads option. Files can be found in message.req.files.

If you are looking to send a multipart POST request from Node-RED to some service, then use the HTTP Request node. How is in the node info panel. Copied below, but best to check the node info panel itself as the text below may become out of date -

File Upload To perform a file upload, msg.headers["content-type"] should be set to multipart/form-data and the msg.payload passed to the node must be an object with the following structure:

 {
     "KEY": {
         "value": FILE_CONTENTS,
         "options": {
             "filename": "FILENAME"
         }
     } 
 } 

>

The values of KEY, FILE_CONTENTS and FILENAME should be set to the >appropriate values.

Here is a sample flow:

[{"id":"f7b0ae63.e74e5","type":"fileinject","z":"aacbc9d.6412c38","name":"","x":140,"y":160,"wires":[["5cb04348.8b9e2c"]]},{"id":"5cb04348.8b9e2c","type":"function","z":"aacbc9d.6412c38","name":"","func":"msg.headers = {\n    \"content-type\" : 'multipart/form-data'\n    };\nlet databuffer = msg.payload;\n\nmsg.payload = {\n    \"KEY\": {\n        \"value\": databuffer,\n        \"options\": {\n            \"filename\": \"myfile.png\"\n        }\n    }\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"x":290,"y":160,"wires":[["f04784b6.9e3078"]]},{"id":"f04784b6.9e3078","type":"http request","z":"aacbc9d.6412c38","name":"","method":"POST","ret":"txt","paytoqs":false,"url":"myserver.mybluemix.net/file/input","tls":"","proxy":"","authType":"basic","x":450,"y":160,"wires":[["76de17b4.dc2de8"]]},{"id":"76de17b4.dc2de8","type":"debug","z":"aacbc9d.6412c38","name":"File has been sent","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":670,"y":160,"wires":[]}]
chughts
  • 4,210
  • 2
  • 14
  • 27
  • I was looking for a way to create the multipart/form-data request itself from within Node-RED. I think what you are referring to is where Node-RED is the receiving end of the request. – libzz May 23 '19 at 01:36
  • I have amended my answer to reflect that. – chughts May 23 '19 at 11:01
  • It seems the node you're describing refers to `node-red-contrib-http-request-multipart`. I had the impression that this node is broken since the node properties are not properly rendered. In any case, I will try it out and get back to you in a sec. – libzz May 24 '19 at 06:22
  • No its the out of the box HTTP Request Node. You get it with a vanilla Node-RED install. – chughts May 24 '19 at 08:55
  • I'm not sure what version "vanilla Node-RED" is but I'm running on `0.19.5`. The description in your answer is not in the node info. Is that really the out-of-the-box HTTP request node? In any case, I tried using the out-of-the-box one and the request sent is not multipart despite following the structure. – libzz May 27 '19 at 02:35
  • Current latest version is 0.20.5 – chughts May 28 '19 at 08:54
  • I can't seem to find the information you shared about how to form the payload's object structure. Can you provide the source ? – libzz Jun 03 '19 at 07:52
  • You need to specify which version of node-red you are running, as the response to how will differ. – chughts Jun 03 '19 at 12:54
  • The latest version of node-red has this functionality out of the box, but you need to clarify what you are trying to do, as you appear to be hopping between: A problem that would be solved by the http-in node allowing a multipart form input in your node-red instance, where the form comes from a webpage (which might have been delivered by node-red) or another application outside of node red. Or a problem that would be solved by the http-request node where your node red flow submits a multipart request to a 3rd party application. – chughts Jun 03 '19 at 12:54
  • 1
    My question is very straight forward: I need to create/generate a multipart request *FROM WITHIN* node-red. You keep on saying to use Http-in when it doesn't resolve anything at all as far as the main question is concerned. Using http-in implies the data comes from somewhere else (e.g. a file upload) -- which isn't the use case I was working on. – libzz Jun 04 '19 at 02:39
  • "Or a problem that would be solved by the http-request node where your node red flow submits a multipart" -- that is exactly what I did in my own answer. I was just wondering where your answer came from as it doesn't work at all. You still didn't provide your source. I don't understand why you need **MY** node-red version to provide **YOUR** source. – libzz Jun 04 '19 at 02:42
  • Sample flow has been added to answer, but it is from an instance running v 0.20.5 of Node-RED – chughts Jun 04 '19 at 09:06
0

It appears creating a multipart/form-data request directly on the HTTP request node is not yet supported. However, it's possible to manually create the multipart payload on a function node and feed it to the out-of-the-box HTTP request node.

Basically, feed to the HTTP request node a payload like so (a snippet from flows.nodered):

msg.headers = {
    "Content-Type": "multipart/form-data; boundary=------------------------d74496d66958873e"
}


msg.payload = '--------------------------d74496d66958873e\r\n'+
'Content-Disposition: form-data; name="select"\r\n'+
'\r\n'+
'true\r\n'+
'--------------------------d74496d66958873e\r\n'+
'Content-Disposition: form-data; name="print"\r\n'+
'\r\n'+
'true\r\n'+
'--------------------------d74496d66958873e\r\n'+
'Content-Disposition: form-data; name="file"; filename="'+msg.filename+'"\r\n'+
'Content-Type: application/octet-stream\r\n'+
'\r\n'+
msg.payload+'\r\n'+
'--------------------------d74496d66958873e--\r\n';


return msg;

The format of the multipart payload is thoroughly discussed in discourse.nodered.
A sample flow is also provided in flows.nodered.

libzz
  • 589
  • 2
  • 10
  • 29
  • This answer is only valid if you are running an old version of node-red. In newer versions both the HTTP In and HTTP Request nodes can handle multi-part. The link to the sample flow you provide makes use of the new multi-part capabilities in the HTTP In node. – chughts May 28 '19 at 08:56
  • As I commented in your answer, the question is not about handling (i.e. receiving) multipart requests. Rather, it's about CREATING a multipart request within Node-RED. In fact, the links I provided are answers from the creators of Node-RED. So if I'm missing something, please do enlighten. – libzz Jun 03 '19 at 07:39