Closed mahsashadi closed 3 years ago
By "host" do you mean via the browser file selection dialog in this case ?
If so, try something like this:
export default function MyComponent (props) {
let currentItem
const input = React.createRef()
const [selected, setSelected] = React.useState({});
const selection = ['file1', 'file2', 'file3']
const onBrowse = item => {
currentItem = item
input.current.click()
}
const onUpload = async () => {
const items = Object.keys(selected)
for (let i = 0; i < items.length; i++) {
await core.make('osjs/vfs')
.writefile(`home:/${items[i]}`, selected[i])
}
}
const onChange = (ev) => {
setSelected({
...selected,
[currentItem]: ev.target.files[0]
})
}
React.useEffect(() => {
input.current.addEventListener('change', onChange)
return () => {
input.current.removeEeventListener('change', onChange)
}
}, [input])
return (
<div style={{ overflow: 'hidden', position: 'relative' }}>
{selection.map((item) =>(
<div>
<label>{item}:</label>
<input key={item} value= {file[item]}></input>
<button onClick={onBrowse(item)}>Browse</button>
</div>
))}
<input
type="file"
ref={input}
style={{ visibility: 'hidden', position: 'absolute', top: '-10000px', left: '-10000px' }}
/>
<button onClick={onUpload}>Upload</button>
</div>
)
}
yes, Thank you, I forgot about input with file type !
I already have another problem after uploading in osjs (not related to osjs itself), if you have time to take a look.
I need to upload these files remotely with a post request. In api curl command I see -F option for each file, for example one as below
-F "keyfile = @somefile.key; type=application/x-iwork-keynote-sffkey"
I first createReadStream for each file (with their realPaths) and then I use below formdata in axios data, but it does not work.
formdata.append('keyfile', filestreams['keyfile]);
formdata.append('keyfile', type=application/x-iwork-keynote-sffkey);
Can you help me where the problem is? I guess the problem is in the way I use formdata.append()
This is how you compose a file upload with form data:
const blob = new Blob(binary, { type: 'application/x-iwork-keynote-sffkey' })
formData.append('keyfile', blob, 'somefile.key')
you mean that I do not need using createReadStream
first?
You can use a stream, but that does not allow you to set the mime type yourself:
formdata.append('keyfile', filestreams['keyfile]);
Ideally this should work though.
you mean that I do not need using createReadStream first?
I can't really answer this without knowing a bit about the code. You can use a Blob, File or ReadableStream. But what is best for you, I dunno.
I have below function client-side:
async function uploadKeys(){
let paths={};
//upload in osjs
const a = Object.keys(keyFiles).map(async item => {
await vfs.writeFile(`home:/${item}`, keyFiles[item])
paths[item] = `home:/${item}`
})
await Prmise.all(a);
//call my API
await axios.post(proc.resource('uploadkeys'), {filesPath:paths})
.then(res=>{})
.catch(err=>{}
}
and below functions server-side in some service-provider
async uploadKeys(req,vfs){
return new Promise(async (resolve, reject)=>{
const formdata = new formdata();
let paths = req.body.filespath
let fileStreams = await this.getFileData(paths, req.session.user, vfs);
formdata.append('keyfile', fileStreams['keyfile'])
// formdata.append() for other files
await axios.post(myendpoint, formdata, {
maxContentLength: Infinity,
maxBodyLength: Infinity,
headers:{'accept':'application/json','content-type':'multipart/form-data'}
}).then(res=>{})
.catch(err=>{})
})
}
async getFileData(paths, user, vfs){
let realPaths = {};
let fileStreams = {}
//getting real paths
const a = Object.keys(paths).map(async item => {
realPaths[item] = await vfs.realPath(paths[item], user)
})
await Prmise.all(a)
//getting streams
Object.keys(realPaths).map(item => {
fileStreams[item] = await vfs.realPath(realPaths[item])
})
return fileStreams
}
My API is something like this:
curl -x POST "myendpoint -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "keyfile=@myfile.key;type=sometype"
But my response is not what I expected. By the way I did not copy and paste the code if there is a mistake.
That implementation looks a bit strange, and it looks like you're not actually creating streams :thinking:
async uploadKeys(req, vfs) {
const formData = new FormData()
const streams = await this.getFileData(req.body.filespath, req.session.user, vfs)
if (!streams.keyfile) throw new Error('No keyfile stored')
formData.append('keyfile', fs.createReadStream(streams.keyfile))
return axios.post(url, formData, {
maxContentLength: Infinity,
maxBodyLength: Infinity,
headers:{ accept: 'application/json', 'content-type':'multipart/form-data' }
})
}
// Convert virtual path map to real path map
async getFileData(paths, user, vfs) {
const promises = Object
.entries(paths)
.map(([k, v]) => vfs.realPath(v, user).then(r => ([k, r]))
const result = await Promise.all(promises)
return Object.fromEntries(result)
}
That implementation looks a bit strange, and it looks like you're not actually creating streams
Oh, since I could not copy the code,I made a mistake in typing here.
Object.keys(realPaths).map(item => { fileStreams[item] = await vfs.realPath(realPaths[item]) })
It is a typing error, In code, I truly get the stream as below:
fileStreams[item] = fs.createReadStream( realPaths[item])
So the problem still persists ?
Yes, I think the logic of your code and mine are the same.
What's the actual error/result you're getting on the other side of this ?
What's the actual error/result you're getting on the other side of this ?
It does not get the response code 200 with true file input, as the corresponding curl command does.
This is how you compose a file upload with form data:
How can I change the code I tell you in previous comments with Blob?
I guess you're using something like this right ? https://www.npmjs.com/package/form-data
Looks like you maybe can do this:
.append('field', stream | buffer, { contentType: 'foo/bar' })
headers:{'accept':'application/json','content-type':'multipart/form-data'}
The problem was only about headers. Instead of using 'content-type':'multipart/form-data'
, I use formData.getHeaders()
and now the response is what I expected.
Thanks a lot :+1:
Hi I need to select some files from my host OS in one form of my application. So How can I open host OS file explorer window in onClick property of browse buttons . Afterwards these files are needed to be uploaded in OSJS file system.
Could you help me with this scenario?