Custom widget with file upload function to be used on public facing forms

Hi

As per the title, I’m trying to build a custom widget which enables the user to upload a file.

I’ve had a look at the dropzone widget in the AppShare, but this isn’t suitably for us, as we’re looking to develop something more along the lines of GDS standards.

However, through looking at the dropzone widget code, I had a look at the Code Studio documentation for record.save_uploaded_files().

Having set up the example, it works, but only for internal pages. Not for external public facing (webpage authenticated) pages.

It fails with the error (taken from browser console)…

…w/webpage/210GBLCR1?context_record_id=264291&webpage_token=c2c78a172669fc16280be441bf7db5429d9583ab7a1c012834edc231579d63d8&webpage_subpage_id=PAG0000210GBLCR1&widget_action=upload
403 (Forbidden)

And in the detective, I see…

I can see that the ‘webpage_token’ is different to the one displayed in by browser when I submitted the form, so suspect this may be contributing to the problem.

Is what I’m attempting possible (I’m assuming it is, as there’s a native Netcall file upload component), and if so, what is, and how do I build the URL to upload the file to?

Hi,

So the below code is a very crude example of a file upload, it works in a widget and on a public webpage, havent tried this on an authenticated, but hopefully this would work.

main.html

<input type="file" class="file_upload" />
<button class="btn btn-primary" @click.prevent="test_event">Upload</button>

main.js - the REL0000249GBGSY1 a relationship to a file object

return {
	action_upload: function() {
		var item = cs.record(554229);
		var result = item.save_uploaded_files('REL0000249GBGSY1');
		return { blah :123 };
	},
	get_template_data: function() {
		...
	},
	get_settings: function() {
		...
	}
}

frontend.js

export default {
	methods: {

		test_event: function (e) {

			let SELF = this;
			let fileInput = document.querySelector('.file_upload');

			var page_id = /\[(PAG.*?)\]/.exec(SELF.mats.input_name);
			var cell_id = /\[(PCL.*?)\]/.exec(SELF.mats.input_name);

			if (page_id == null || page_id[1] === undefined || cell_id == null || cell_id[1] === undefined) {
				return false;
			}

			var postData = new FormData();
			if (fileInput != null) {
				postData.append('fragment_action', 'upload');
				postData.append('files[]', fileInput.files[0]);
				postData.append('form_check_ajax', CSRF);
				postData.append('action_page_id', page_id[1]);
				postData.append('action_cell_id', cell_id[1]);
			}

			SELF.mats.widget.ajax('upload', {
				type: "POST",
				data: postData,
				processData: false,
				contentType: false,
				success: function (e) {
				}
			});
		}
	}
}

if successful you should see the below response in the console

{"result":"success","response":{"blah":123}}

Use this at your own risk as none of this is properly documented it could change in the future.

1 Like