I want to be able to upload multiple files. My knowledge in react is lacking but I seen many react packages that handle multiple files upload such as react-dropzone react-dropzone-uploader etc…
I’m struggling to implement them with Streamlit. Ideally, I want to upload a bunch of files directly to s3 and then just use st.image to preview them or get the list of images as output of react component and then us st.image image to preview them without having to upload to cloud.
If anyone can point me in the right direction it will be nice.
So far I can log the accepted files but not sure what to do with them. They only contain filename without absolute path.
import React, { useCallback } from 'react';
import { useDropzone } from 'react-dropzone'
const App = () => {
const maxSize = 1048576;
const onDrop = useCallback(acceptedFiles => {
console.log(acceptedFiles);
}, []);
const { isDragActive, getRootProps, getInputProps, isDragReject, acceptedFiles, rejectedFiles } = useDropzone({
onDrop,
accept: 'image/png, image/jpeg',
minSize: 0,
maxSize,
});
const isFileTooLarge = rejectedFiles.length > 0 && rejectedFiles[0].size > maxSize;
return (
<div className="container text-center mt-5">
<div {...getRootProps()}>
<input {...getInputProps()} />
{!isDragActive && 'Click here or drop a file to upload!'}
{isDragActive && !isDragReject && "Drop it like it's hot!"}
{isDragReject && "File type not accepted, sorry!"}
{isFileTooLarge && (
<div className="text-danger mt-2">
File is too large.
</div>
)}
</div>
</div>
);
};
export default App;
Hey @avn3r, glad to see another person jumping in on the components train!
One thing I want to highlight is that we’re planning on overhauling the file_uploader function in base Streamlit by Q4 this year, so uploading multiple files might be supported before you know it. @karriebear can hopefully speak to this a bit more.
That’s right! We’re actively working on the file uploader enhancements which will include support for multiple files. This is targeted for beginning of Q4.
Regarding your custom component, react-dropzone returns a File object.
To view images without uploading anywhere, rather than using st.image, it would be easier to display them within your react component. react-dropzone actually had this functionality in previous versions but removed it. Luckily they’ve provided an example implementation here
To upload files to S3, you’ll need to send the data to S3. AWS has a SDK available to do this here.
Thanks I got it working with another library react-dropzone-uploader. Can upload up to 500 files without issue the main issue is still communicating back with Streamlit. I would like to just pass the files before upload to streamlit so that I can handle the S3 upload as a background process.
I want to get all the files pass them to st.image and in the background upload them. Right now I been having to upload them directly to S3 and the show them with st.image but that makes the UX slow cuz I have to wait until they upload all the files which can be 1k+ files…
Any suggestions welcomed. I a noob at react… But will try my best. Also can streamlit components work with hooks or functions or only Class Components?
Hey @avn3r. Sure you can use post-hooks React in Streamlit Custom Components I and I think @okld too mostly used React hooks in the beta without any issues, check my D3 React hooks experiments or Synode’s Ace editor for random examples.
Going further, though there are no public examples (yet), you are not limited to React to build Custom Components ! Streamlit Custom Components runs arbitrary HTML/CSS/Javascript in an iframe, as long as you subscribe to specific Streamlit JS events to trigger the rendering and send back data from the component to the Python script. You can find which JS events you need to subscribe to inside the template-reactless folder of the project, in frontend/src/index.tsx.
The React template does all of the subscribing for you inside the withStreamlitConnection component in frontend/src/streamlit/StreamlitReact.tsx for the React template. If you are more of a Angular, Ember, Vue, Svelte, etc…user, you’re free to replicate this event subscription behavior in your preferred JS stack
you should have access to your image files in an array before the handleSubmit (I did not check your code so I’m making an assumption there…), you can display them under your file uploader with one of those React image browser. They are better suited for displaying multiple images rather than a sequence of st.image calls, at least you can control the disposition of the images in HTML/CSS, as a grid of small images or in a carousel. It will be harder to scroll 500+ st.image calls.
Actually st.image is the only widget that allows grid like behavior. I can control how many rows how many columns and I use left and right buttons to display next set of image, so displaying on the streamlit site is pretty decent, only thing I can’t control is the height of the images.
I already got it to work by using react component to directly uploading to S3 and the using st.image. However this requires upload first then display which is a bit too slow. I would prefer direct interaction with Streamlit so that I can use st.image before uploading and then just have a python background process that uploads while I do stuff with the images.
So the main question or place I’m stuck is how to return the list of images (maybe as byte List) in a format that I can read from st.image. In react I can handle an image and I have acceptedFiles but I need something to make them into image bytes list of acceptedFiles or something like that, that st.image can handle.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.