Aryo Pradipta Gema
Aryo Pradipta Gema

Reputation: 1230

How to handle uploaded zip file in Dash plotly?

Using the dcc.Upload, you can build a drag and drop or button-based uploading feature in Dash Plotly dashboard. However, there is a limit in the documentation on handling a specific filetype such as .zip. Here's a snippet of the uploading html:

dcc.Upload(
    id='upload_prediction',
    children=html.Div([
        'Drag and Drop or ',
        html.A('Select Files'),
        ' New Predictions (*.zip)'
    ]),
    style={
        'width': '100%',
        'height': '60px',
        'lineHeight': '60px',
        'borderWidth': '1px',
        'borderStyle': 'dashed',
        'borderRadius': '5px',
        'textAlign': 'center',
        'margin': '10px'
    },
    accept=".zip",
    multiple=True
)

Then when I try to examine the uploaded file with this snippet:

@app.callback(Output('output_uploaded', 'children'),
              [Input('upload_prediction', 'contents')],
              [State('upload_prediction', 'filename'),
               State('upload_prediction', 'last_modified')])
def test_callback(list_of_contents, list_of_names, list_of_dates):
    for content in list_of_contents:
        print(content)

The content-type after uploading is ‘data:application/x-zip-compressed;base64’. How to handle this type of file in Dash Plotly (for example to extract it somewhere)?

A similar question was asked in the plotly forum without answers: https://community.plot.ly/t/dcc-upload-zip-file/33976

Upvotes: 2

Views: 2620

Answers (1)

Aryo Pradipta Gema
Aryo Pradipta Gema

Reputation: 1230

Dash Plotly provides the uploaded file in the base64 string format. What you need to do is to decode it first, then handle it as bytes string which later can be used to initialize ZipFile class (It's a built-in tool in python).

import io
import base64
from zipfile import ZipFile


@app.callback(Output('output_uploaded', 'children'),
              [Input('upload_prediction', 'contents')],
              [State('upload_prediction', 'filename'),
               State('upload_prediction', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
    for content, name, date in zip(list_of_contents, list_of_names, list_of_dates):
        # the content needs to be split. It contains the type and the real content
        content_type, content_string = content.split(',')
        # Decode the base64 string
        content_decoded = base64.b64decode(content_string)
        # Use BytesIO to handle the decoded content
        zip_str = io.BytesIO(content_decoded)
        # Now you can use ZipFile to take the BytesIO output
        zip_obj = ZipFile(zip_str, 'r')

        # you can do what you wanna do with the zip object here

Upvotes: 7

Related Questions