formio.js
formio.js copied to clipboard
[BUG] `TypeError: Provider is not a constructor` for File uploads since v4.14.0
When attempting to upload a file using any storage provider (including base64), Formio.js shows an TypeError: Provider is not a constructor for File uploads
error instead of uploading the file.
This issue occurs since 4.14.0
and persists in 5.0.0-rc.4
. It is NOT giving this error in 4.13.13
.
This error can be observed in the sandbox with the following very simple form:
{
"display": "form",
"components": [
{
"label": "Upload",
"tableView": false,
"storage": "base64",
"webcam": false,
"fileTypes": [
{
"label": "",
"value": ""
}
],
"key": "file",
"type": "file",
"input": true
},
{
"type": "button",
"label": "Submit",
"key": "submit",
"disableOnInvalid": true,
"input": true,
"tableView": false
}
]
}
I can observe this error on Chrome 113 & Firefox 114.
This issue persists in: v5.0.0-rc.18
But I don't experience this issue in v4.14.14
and v4.15.0
.
Issue is present with 5.0.0-rc.19, too. Reason seems to be that the available storage-providers are defined as "arrow functions" which can't be used as constructors (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) But this exactly what formio is doing here
https://github.com/formio/formio.js/blob/dc9784184326173e7e5fd63d4c44dfc9fc9a9ba1/src/Formio.js#L25
But - it looks to me like this code has been there for a long time, and obviously file-upload worked in recent versions.
As a workaround - you can define your own provider - as a class which can be intantiated without a problem. I did it like this
Providers.addProvider("storage","sample-storage-provider",SampleStorageProvider)
SampleStorageProvider is a plain JS or TS class which has to expose two methods - uploadFile and downloadFile.
Unfortunately there is a catch. The FormBuilder is not displaying those providers correctly. They are named "undefined" in the select-list, since the Builder us a "title" property which is not present with the providers registered manually. Besides that no problems for me...
Ah - i worked around the naming - issue. This example is the original Base64-Storage-Provider as a class.
const SampleStorageProvider = class {
uploadFile(file:any, fileName:string) {
const reader = new FileReader();
return new Promise((resolve, reject) => {
reader.onload = (event:any) => {
const url = event.target.result;
resolve({
storage: 'base64',
name: fileName,
url: url,
size: file.size,
type: file.type,
});
};
reader.onerror = () => {
return reject(this);
};
reader.readAsDataURL(file);
});
}
downloadFile(file:any) {
// Return the original as there is nothing to do.
return Promise.resolve(file);
}
}
//ignore the type-script linting error
//@ts-ignore
SampleStorageProvider.title = "SampleStorageProvider"
export default SampleStorageProvider;
The storage providers have always been "arrow" functions, so I do not believe that is related to the issue here.
This is strange because our enterprise product uses this same file upload providers and does not exhibit this behavior. Regardless, I will take a look at resolving this for our 5.x renderer.
Hi Travis,
I was also affected by this issue. I patched formio at this line:
https://github.com/formio/formio.js/blob/4b16aa4aa6dad9a3e71e45c5aef44b46e2ab6e43/src/providers/storage/url.js#L1 Just replace this line const url = (formio) => {
with this one: const url = function Provider(formio) {
Best regards
Ralf
This issue persists in: v5.0.0-rc.30
This looks like it's resolved in v5.0.0-rc.32: 19b1e4fd3dde9c8c60139c7f82e5e075e743b14d Any idea when this will be released?
Thank you for taking the time to report this issue. The issue has been resolved. Closing this thread.