Unzipping

I want to deploy my ML model using streamlit but streamlit can only allow users upload a file at a time. As a result I am trying to allow user upload a zip file containing images so that the images can be extracted at the backed end and use for prediction. Anytime I test the below code, it keeps throwing:

AttributeError: ‘list’ object has no attribute ‘seek’.

How can I solve this.

import altair as alt
import streamlit as st
from PIL import Image
from pathlib import Path
import base64
import io
import pandas as pd
import zipfile
import filetype

st.set_page_config(page_title='Br Classifier', page_icon = 'nm.jpg', layout = 'wide', 
initial_sidebar_state = 'expanded')

image = Image.open(r"C:\Users\taiwo\Desktop\image.jfif")
st.image(image, use_column_width=True)

st.write("""
#CLASSIFICATION

This application helps to classify different classes

***
""")

# pylint: enable=line-too-long
from typing import Dict

import streamlit as st


@st.cache(allow_output_mutation=True)
def get_static_store() -> Dict:
   """This dictionary is initialized once and can be used to store the files uploaded"""
   return {}


def main():
   """Run this function to run the app"""
   static_store = get_static_store()

   st.info(__doc__)
   file_uploaded = st.file_uploader("Upload", type=["png","jpg","jpeg", "zip"], 
   accept_multiple_files=True,)
   with zipfile.ZipFile(file_uploaded,"r") as z:
        z.extractall(".")
            
            
   selected_model = st.sidebar.selectbox(
   'Pick an image classifier model',
   ('CNN_CLASSIFIER', 'Neural Network'))

   st.write('You selected:', selected_model)

if __name__ == "__main__":
    main()

Hi @Taiwo_Osunrinde :wave:

Since you’ve set accept_multiple_files=True, the file uploader returns a list. A zip file may be an element of the list. You can replace the with block with the snippet below:

# Check if files were uploaded
if len(file_uploaded) > 0:
    for file in file_uploaded:
        # If zip file, extract contents
        if file.type == "application/zip":
            with zipfile.ZipFile(file, "r") as z:
                z.extractall(".")
View entire script
import base64
import io
import zipfile
from pathlib import Path

import altair as alt

# import filetype
import pandas as pd
from PIL import Image

import streamlit as st

st.set_page_config(
    page_title="Br Classifier",
    page_icon="nm.jpg",
    layout="wide",
    initial_sidebar_state="expanded",
)
image = Image.open(r"C:\Users\taiwo\Desktop\image.jfif")
st.image(image, use_column_width=True)

st.write(
    """
#CLASSIFICATION

This application helps to classify different classes

***
"""
)

# pylint: enable=line-too-long
from typing import Dict

import streamlit as st


@st.experimental_memo
def get_static_store() -> Dict:
    """This dictionary is initialized once and can be used to store the files uploaded"""
    return {}


def main():
    """Run this function to run the app"""
    static_store = get_static_store()

    st.info(__doc__)
    file_uploaded = st.file_uploader(
        "Upload",
        type=["png", "jpg", "jpeg", "zip"],
        accept_multiple_files=True,
    )

    # Check if files were uploaded
    if len(file_uploaded) > 0:
        for file in file_uploaded:
            # If zip file, extract contents
            if file.type == "application/zip":
                with zipfile.ZipFile(file, "r") as z:
                    z.extractall(".")

    selected_model = st.sidebar.selectbox(
        "Pick an image classifier model", ("CNN_CLASSIFIER", "Neural Network")
    )

    st.write("You selected:", selected_model)


if __name__ == "__main__":
    main()

Hi @snehankekre. Thanks for your response. What i am trying to achieve is that if the user decide not to upload the images one after the other but decide to upload a zip file instead. I want to check the file type first, secondly, if it is a png, jpeg, then it should open (Image.open()) and st.image(). 3rd if it is a zip file, then it should extract all images

You should be able to adapt the above example to your use-case. The basic logic is the same. The snippet already checks if the file type is a zip. If so, the contents are extracted.

Thanks, it worked. I just included an else statement to open the image if it is not zipped

 if len(file_uploaded) > 0:
        for file in file_uploaded:
            # If zip file, extract contents
            if file.type == "application/zip":
                with zipfile.ZipFile(file, "r") as z:
                    z.extractall(".")
            else:
                test=Image.open(file)
                st.image(test)
1 Like

@snehankekre, the extracted images will be extracted into a list right?