Description
Describe the bug
In Microsoft Edge on Windows 10 (Microsoft EdgeHTML 18.19631, Microsoft Edge 44.19631.1.0), when trying to upload a file using FilePond, once the file is selected, the status doesn't proceed past the "Uploading" state with spinner in the UI. There are no console messages, and no AJAX request is made to my /upload endpoint.
File status stays at PROCESSING (3)
This same example works fine in Chrome and Firefox.
My project is using the Rollup bundler, but in reproducing this, I disabled treeshaking and terser minification.
For completeness, my project is loading the following polyfills in Edge (the server returns only the polyfills needed by the requesting browser):
https://cdn.polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.every,Array.prototype.filter,Array.prototype.find,Array.prototype.findIndex,Array.prototype.forEach,Array.prototype.includes,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.some,Array.prototype.values,ArrayBuffer,atob,Blob,console,CustomEvent,DataView,Date.now,document,fetch,Function.prototype.bind,globalThis,Int8Array,JSON,Map,Math.sign,modernizr:es5object,Number.isSafeInteger,Object.assign,Object.freeze,Object.getOwnPropertyDescriptors,Object.getOwnPropertySymbols,Object.is,Object.setPrototypeOf,Object.values,Promise,requestAnimationFrame,Set,String.prototype.includes,String.prototype.padStart,String.prototype.repeat,String.prototype.trim,Symbol,Symbol.asyncIterator,Symbol.for,Symbol.iterator,Uint8Array,URL,WeakMap,WeakSet,XMLHttpRequest
Logs
I've delved into the FilePond library and found that the difference between the working Chrome browser and the not-working Edge browser can be pinpointed to this line:
// if no file loaded we'll wait for the load event
if (!(state.file instanceof Blob)) {
starting at line 228 in src/js/app/utils/createItem.js
.
In Chrome, this code block is entered, since state.file is a Blob
object.
In Edge, this code block is not entered, since it is a File
object.
This can be resolved with the following change (using an existing utility function used elsewhere in the code for the file check):
// if no file loaded we'll wait for the load event
if (!isFile(state.file)) {
Once this code is fixed, there is a second code issue blocking uploads.
Starting at line 39 in src/js/app/utils/createFileProcessorFunction.js
:
// Turn into an array of objects so no matter what the input, we can handle it the same way
(file instanceof Blob ? [{ name: null, file }] : file).forEach(item => {
formData.append(name, item.file, item.name === null ? item.file.name : `${item.name}${item.file.name}`);
});
My understanding of the parent createFileProcessorFunction
that this code resides in (based on the variable names, code structure, etc), is that this function only ever deals with a single file object (whether that be Blob
, File
, or something else) - therefore, the operation of a forEach in the right side of the ternary (when file
is not a Blob
) is not correct, since if file
is a File
, it does not have the forEach
method.
Changing this code as follows has resolved my issue in both Edge and Chrome:
[{ name: null, file }].forEach(item => {
formData.append(name, item.file, item.name === null ? item.file.name : `${item.name}${item.file.name}`);
});
(it can be simplified further if indeed this parent function only operates on a single file, as the forEach
is redundant in this case).
To Reproduce
I am using filepond-react (though the error is happening inside the main filepond library).
Upload a file (in my case, an .xlsx file).
Error happens both on localhost server development version and online HTTPS hosted version.
Here is my React component (with added logging of every lifecycle event):
<FilePond
allowMultiple={false}
maxFiles={1}
allowRevert={true}
ref={ref => (this.pond = ref)}
files={this.state.files}
server='/api/upload'
oninit={() => {
console.log('oninit');
}}
onwarning={(error, file, status) => {
console.log('onwarning', error, file, status);
}}
onerror={(error, file, status) => {
console.log('onerror', error, file, status);
}}
onaddfilestart={(file) => {
console.log('onaddfilestart', file);
}}
onaddfileprogress={(file, progress) => {
console.log('onaddfileprogress', file, progress);
}}
onaddfile={(error, file) => {
console.log('onaddfile', error, file);
}}
onprocessfilestart={(file) => {
console.log('onprocessfilestart', file);
}}
onprocessfileprogress={(file, progress) => {
console.log('onprocessfileprogress', file, progress);
}}
onprocessfileabort={(file) => {
console.log('onprocessfileabort', file);
}}
onprocessfilerevert={(file) => {
console.log('onprocessfilerevert', file);
}}
onpreparefile={(file, output) => {
console.log('onpreparefile', file, output);
}}
onupdatefiles={(fileItems) => {
console.log('onupdatefiles', fileItems);
this.setState(
{
files: fileItems.map((fileItem) => {
return fileItem.file;
}),
uploads: pick(
this.state.uploads,
this.pond.getFiles().map(
(file) => file.filename
)
)
}
);
}}
onprocessfile={(error, file) => {
console.log('onprocessfile', error, file);
if (file.status === 5) {
// uploaded file
try {
const serverId = JSON.parse(file.serverId);
this.setState(
(prevState) => {
return {
uploads: {
...prevState.uploads,
[file.filename]: serverId.filename
}
}
}
);
} catch (e) {
// TODO: do something with error?
}
}
}}
/>
Expected behavior
File should be uploaded in Edge, matching the behaviour shown in browsers such as Chrome.
Stacktraces
With the above full logging, here is the different outputs:
Edge (not working)
oninit
onupdatefiles [object Object]
onaddfilestart [object Object]
onaddfile null [object Object]
onupdatefiles [object Object]
Chrome (working)
oninit
onupdatefiles [{…}]
onaddfilestart {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …}
onaddfile null {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …}
onupdatefiles [{…}]
onpreparefile {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} File {_relativePath: "", name: "google3.xlsx", lastModified: 1587694216867, lastModifiedDate: Fri Apr 24 2020 04:10:16 GMT+0200 (Central European Summer Time), webkitRelativePath: "", …}
onprocessfilestart {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …}
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.07872040476051442
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.18288578883755874
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.3299895755112473
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.4611902501121047
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.538320343665336
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.5804635906583386
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.6671355514552687
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.8444552510673365
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.8945500540967548
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.930332056260625
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 0.9486206351443808
onprocessfileprogress {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …} 1
onprocessfile null {getMetadata: ƒ, setMetadata: ƒ, abortLoad: ƒ, abortProcessing: ƒ, …}
Information about your project:
- Your browser and the version: Microsoft EdgeHTML 18.19631, Microsoft Edge 44.19631.1.0 (vs Chrome 83 comparison)
- Your operating system: Windows 10 (latest Insider preview)
- FilePond version: 4.13.4 and 4.13.7