Input file in uibuilder V7

Hello.

I'm pretty new in Node-Red and uibuilder and i'm totally not a web guy. Learning by doing. I created a form via uib-element node. One of inputs is a file upload. When I'm submitting form I see message coming about file upload separately to _ui message with form fields content. After form submitting, I would like to import uploaded file (xlsx) into database (I need buffer only), including also other fields values from the form.
I didn't find any good way to kind of merge messages to process further. However, in _ui message under form->appropriate object->value, I found tempUrl key with value "blob:http://{ip of my server}:1880/ee205300-e317-4abc-8d4f-6b6e7381b21d". if I use this url in browser - i'm able to download uploaded file. Maybe I could get buffer from this url?
Or maybe I'm doing completely wrong?
Sorry for probably pretty stupid questions.

No such thing :smile: Generally only stupid answers!

I can see, from a quick browse of the docs, that I have really failed to properly document file uploads.

There was something here in a release note.

When using a form on a page and using <input type="file">, if a file is selected by the client and the file is less than the size of the maximum message size, the file will be automatically uploaded to Node-RED when the form is submitted (assuming you use uibuilder.eventSend(event) to submit the form). The upload is a message with file details and the file itself as a buffer in msg.payload.

If a file input is sent back to Node-RED, you will get a 2nd message that contains the file:

Where the file content is in msg.payload as a buffer.

As you have noted, the blob URI works in the browser but does not work for an http-request node. So it could be passed to another client browser but if you want Node-RED to have the file, you need to process the 2nd message with the msg.topic "file-upload".

There is a full example demonstrating the uib-element node in the examples library under uibuilder. It includes a reasonably comprehensive form example with file-upload.

If you need to process a file upload outside of uib-element's construction, you have access both to the eventSend function that you can attach to an input tag or a form tag which is what uib-element uses. Or you can use the [uibuilder.uploadFile()](UIBUILDER Documentation v7) function which is what eventSend uses internally.

Please note the limitations on file sizes though. If you need to upload a file larger than 1MB, you will need to change some settings to allow larger message sizes. Details in that last link.


Incidentally, if you wanted to allow a user to upload a file and then have it served to all users, you could pass the upload message to a uib-save node.

Thank you for quick reply. Most of the things I discovered myself already, as I wrote.

This is where I stuck fund file buffer in a separate message. I thought to join messages, but it looks a bit ugly just to wait for another one message or by seconds... What if someone else will submit a form and second message will not be file upload? Especially that there going to be multiple forms and some of them will not have file upload. Of course I would look into form ID, which I suppose I could provide as HTML ID in uib_element node, but _ui message under form->id providing self generated "form X", which saying me nothing. Another thing I found is that file uploaded even if form is not valid. This a bit surprised me as well. I most probably could control submit button enable/disable by watching changes on the form, but as I wrote, I'm far with knowledge how to yet.

Will try to find. Didn't found before. Might be would not asking.

You mean to do a post to another url and catch by http in?

Read documentation but not really understood how to use. :frowning:

No. Files used only to extract information and insert into database. All users fetching information from there.

Each will result in its own file-upload message and you can tell they are different and who they are from by enabling the advanced _uib extension:

Hmm, so I've spotted a slight weakness in the upload message - it should include the input tag's HTML ID and name attributes. You get these in the form upload message but not in the file-upload. Added to the backlog.

You do get the filename in both messages so it is possible to tie them together if you need to, but not very friendly of me. Sorry about that.

I do have another fix to publish so this could go into the same release. I'm hoping to get some time later this week.

Yes, that's a decision I took because people might want to do more validation and messaging from Node-RED and I didn't want to totally block that. The form message contains a flag to indicate if the form is valid and flags for each form element to show their validity.

The other reason for not auto-blocking is that the same process handles individual inputs - even without a wrapping form. You might choose to do everything in Node-RED and indeed, you might find that valuable if you lack front-end coding knowledge.

Just add a switch node on the uibuilder node's output if you want to block invalid forms.

Hi,

I wrote before that HTML_ID of the form not appearing in form submitting message also (V7.1).
This is what I would expect under _ui->form.

I understand, different cases - different needs. This is a small problem.

Exactly how i'm doing now.

I found form example. Unfortunately I'm interested in such form processing part after submit. Exactly this is not really explained there.
Just an idea, maybe for such cases, when form submission happening and multiple messages to be generated, it's possible to add msg.parts for these connected messages? The it would be peanut to join them in one message.

Ah, interesting idea! I will look into that for sure.

I suppose, by adding all parts


join of messages will be fully automated and as parts.id could be used form submission _msgid or maybe _socketId

Added to the backlog so I don't forget. I will need to check how feasible it is but I think I will be able to do something.

Assuming that my wife doesn't fill up my leave-time with house/family activities, I'm hoping to do some uibuilder work later this week. :grin:

Great. Just remember, happy wife = happy life. :smiley:
I just emulated msg.parts and did join in automated mode - works great.
Then I used join in manual mode in such config

where msg.parts.key was set in change node to either msg.topic (if exists) or simply to "form" (maybe form could also get topic in original message?).
Result was even better I think:


Even easier for further automation since each part of payload could be referred by name.
Just dropping you some ideas, maybe you will find something valued.

Rechecked the code and the form's id attribute IS included in the data. However, it will auto-create an id if you haven't given one in the first place and the no-code uib-element form adds its ID to the parent div and not to the form itself. That means that the response will always have an id of form-x where x is a number, usually 1 unless you've added other forms first.

This will be fixed in the upcoming release. where the form id will be form-<elementId> since the element ID you set on uib-element should always be unique on the page.

This turns out to be simultaneously more complex and less useful than I first thought.

The issue is that, when processing a form, the system does not "know" how many uploads will be generated. It would have to process the whole form and hold everything in memory before sending any messages. This would be quite inefficient and might easily break things if uploading a load of really large files.

To further complicate things, a file upload input can allow multiple files to be selected. So you could have multiple inputs each with multiple files.

And, as a final complication, I have a backlog item to allow auto-splitting of messages for large messages and that would take priority for using the msg.parts feature

So instead, I am adding appropriate meta-data to each upload:

  • A seq number and a seqCount for multi-file submissions.
  • id is the HTML id of the source input element.
  • formId is the HTML id of the form that the input element belongs to. The formId won't exist if the input was submitted without a form.
  • The temporary file URL. This is probably the easiest property to use if you need to merge data with the main message.
  • I've also now added the clientId, pageName and tabId to the message. This is duplicate data if you've turned on the _uib property in your uibuilder node but it should make it easier to filter/switch messages in your flows.
  • Finally, I've added the data object which contains any data-* attributes from the input element.

So if you want to combine other form inputs with your file upload, Save the form message to a flow variable - referenced by the client ID (the socket ID changes too easily) to allow for multiple, overlapping, client submissions. Then, for each file upload, compare msg.tempUrl against msg.payload["input-id"][0].tempUrl (where the id and offset might be different of course).

If you want to make your life even easier and you are prepared to add some front-end logic, you could use change events on your inputs to add data attributes to your file input elements. I can show you how to do that if you like.

I'm also creating a new "how to" document explaining this stuff.

As a side-note, don't forget that, with uibuilder and the no-code nodes - what is created is standard HTML. This means that if your form doesn't change very much, you may want to consider using uib-element to do the initial page creation but then save the updated page back to the index.html file. By doing that, you can then go tweak your form and the page manually and you benefit of not needing to send the form to every newly connected or reloaded client - so the page load is faster and can be cached by the browser making it faster still. Check out the examples for the uib-save node to see how you can do this automatically without any coding.

On further consideration, I don't think that joining the file upload messages would be sensible. All of the metadata for the files is in the form upload message and the file uploads contain large buffers which it would not make sense to merge. If you really have an overriding reason to do so and understand the potential consequences, then - with the new metadata - you should be able to add the msg.parts data yourself.


I've a few additional tests to run, some documentation to update and a few other things to finish off. But you can expect a new version of uibuilder - v7.2.0 - very soon with these and some other fixes and new features (such as the new uibuilder sidebar UI!).

Hi,

Thank you for detailed reply. I clearly see complications. I suppose new version will solve my problems. Currently I'm creating msg.parts myself, but it looks ugly.
About joining file upload message and form submission message, it's needed because other form inputs used when importing file. Now thinking maybe I can simply enrich file upload message with form submission payload information....

I need to read more about this. Not used flow variables before.

This would be great.