I have created a custom plugin and i have a requirement to upload file to server. I am trying to do it using EuiFilePicker. API which I am using to upload file is accepting data in form-data format. Below is my code.
component.ts :-
const [files, setFiles] = useState({});
const [large, setLarge] = useState(true);
const onFileChange = files => {
setFiles(files);
};
const onSubmit = () => {
const data = new FormData();
data.append('file', files[0]);
data.append('remark', 'Test');
data.append('case_id', 'INC-000001');
const submitRequestOptions = {
method: 'POST',
body: data
}
props.http.post(window.location.origin + '/casemanagement/files/', submitRequestOptions).then((res) => {
console.log("Success Response", res);
}).catch((error: ResponseError) => {
console.log("Error", error);
});
}
const renderFiles = () => {
if (files.length > 0) {
return (
<ul>
{Object.keys(files).map((item, i) => (
<li key={i}>
<strong>{files[item].name}</strong> ({files[item].size} bytes)
</li>
))}
</ul>
);
} else {
return (
<p>Add some files to see a demo of retrieving from the FileList</p>
);
}
};
return (
<EuiPanel paddingSize="m" className="mr10 ml10">
<EuiFlexGroup>
<EuiFlexItem>
<EuiFilePicker
id="asdf2"
multiple
initialPromptText="Select or drag and drop multiple files"
onChange={files => {
onFileChange(files);
}}
display={large ? 'large' : 'default'}
aria-label="Use aria labels when no actual label is in use"
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiText>
<h3>Files attached</h3>
{renderFiles()}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
<EuiButton fill id='btnStep4Submit' color="primary" onClick={() => { onSubmit()}}>
<strong>Submit</strong>
</EuiButton>
</EuiPanel>
)
Hi @praveer
Can you confirm that the file data present (files[0]) when calling onSubmit is correct or incorrect?
If the data is correct, then EuiFIlePicker is working as expected and the problem likely lies with the onSubmit function.
Thanks. It appears that EuiFilePicker is working as expected. The error is coming from the HTTP request, but I'm familiar enough with plugin APIs to diagnose the issue beyond that.
I'll ping someone with more knowledge on the subject.
I think the problem is coming from the submitRequestOptions. I believe the HTTP client is not automatically appending the Header to post the FormData. So the body-parser on the server doesn't know how to handle the contents of the body and fails with Bad request.
Would you mind manually adding the property headers: {'content-type': 'multipart/form-data'} to the submitRequestOptions and try if that fixes the issue?
From the response, I get that the multipart header is missing the boundary. You might need to add it. If you look at the headers Postman adds, when using Content-Type: 'multipart/form-data', the boundary= bit needs to be added (MDN Web docs).
Here are some examples of possible options: javascript - fetch - Missing boundary in multipart/form-data POST - Stack Overflow. Apparently, some users made it work by explicitly setting Content-Type: undefined, and letting fetch to populate it automatically (FYI, we use fetch under the hood). Others had to add 'Accept': '*/*' to the request as well
I tried ur suggestion, but in the above suggestion file is going as binary format and getting bad request error.
In EUIFilePicker how can I get file path as I am trying to send payload as below for that I need to get the file path of uploaded file, but I couldn't find it in EUIFilePicker
var formdata = new FormData();
formdata.append("file", fileInput.files[0], "/C:/Users/Praveer.Nair/Desktop/cases.json");
formdata.append("remark", "Test");
formdata.append("case_id", "INC-000001");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow'
};
EuiFilePicker is really just a styled native HTML <input type="file"> element, so all the data you get is from the Web API: File - Web APIs | MDN.
Looks like webkitRelativePath might be helpful, but EUI does not actually handle the file itself or provide any data beyond the Web API.
I just reread the spec and webkitRelativePath will not be helpful for your case:
The File.webkitRelativePath is a read-only property that contains a USVString which specifies the file's path relative to the directory selected by the user in an <input> element with its webkitdirectory attribute set.
It only works when selecting directories and when using the webkitdirectory attribute.
Unfortunately the data you want is not available in the Web API.
Although EuiFilePicker cannot provide this data, formdata.append("file", fileInput.files[0]) appears to be sufficient per the FormData spec: FormData: append() method - Web APIs | MDN
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant
logo are trademarks of the
Apache Software Foundation
in the United States and/or other countries.