1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Python] Dash application requires deletion of uploaded excel files from the uploads folder

Discussão em 'Python' iniciado por Stack, Outubro 5, 2024 às 11:32.

  1. Stack

    Stack Membro Participativo

    The idea is that multiple Excel files can be uploaded and displayed, there is also the ability to delete each file from view and the uploads folder. The file deletion is failing. Here is the code with the error "Filename is None, skipping deletion". The deletion button is clickable and attempts to delete the file but eventually fails.

    import os
    from dash import dcc, html, dash_table, Input, Output, State, callback, callback_context
    from dash.dependencies import ALL
    import dash_bootstrap_components as dbc
    import base64
    import datetime
    import io
    import pandas as pd

    # Import file management functions
    from constants.index import table_style, cell_style, header_style

    from components.image_component import create_image

    # Fetch upload icons
    upload_icon = "assets/images/icons/upload-colored-icon.png"
    download_icon = "assets/images/icons/download-icon.png"

    # Upload directory
    upload_directory = "uploaded_files"

    # Ensure the upload directory exists
    if not os.path.exists(upload_directory):
    os.makedirs(upload_directory)

    # Define custom loader styles
    loader_style = {
    "position": "fixed",
    "top": "0",
    "left": "0",
    "width": "100%",
    "height": "100%",
    "backgroundColor": "rgba(255, 255, 255, 0.8)", # Semi-transparent background
    "display": "flex",
    "justifyContent": "center",
    "alignItems": "center",
    "zIndex": "9999", # Ensure it's on top of everything
    }


    def file_uploader():
    return html.Div(
    [
    dcc.Upload(
    id="upload-data",
    children=dbc.Button(
    className="upload-button",
    id="upload-button",
    children=[
    create_image(image_path=upload_icon, image_style="icon"),
    html.Span("Upload Files"),
    ],
    ),
    multiple=True,
    ),
    dbc.Alert("The uploaded files should follow predefined formats.", className="upload-alert"),
    dcc.Loading(
    id="loading-spinner",
    type="circle",
    fullscreen=True,
    style=loader_style,
    children=html.Div(id="output-data-upload"),
    ),
    ]
    )


    def save_file(contents, filename):
    """Save the uploaded file to the server."""
    content_type, content_string = contents.split(",")
    decoded = base64.b64decode(content_string)

    # Create the full path for the file
    file_path = os.path.join(upload_directory, filename)

    # Write the file based on its type
    try:
    with open(file_path, "wb") as f:
    f.write(decoded)
    except Exception as e:
    print(f"Error saving file {filename}: {e}")
    return html.Div([f"There was an error saving the file: {e}"])

    return file_path # Return the path of the saved file


    def load_saved_files():
    """Load and display saved files from the server."""
    saved_files = []
    for filename in os.listdir(upload_directory):
    file_path = os.path.join(upload_directory, filename)

    # Display each saved file
    if filename.endswith(".csv"):
    df = pd.read_csv(file_path)
    elif filename.endswith(".xls") or filename.endswith(".xlsx"):
    df = pd.read_excel(file_path)
    else:
    continue

    saved_files.append(
    html.Div(
    [
    html.Div(
    className="flex",
    children=[
    html.H5(filename),
    dbc.Button(
    "Delete",
    id={"type": "delete-button", "index": filename},
    color="danger",
    n_clicks=0,
    ),
    ],
    ),
    dash_table.DataTable(
    df.to_dict("records"), [{"name": i, "id": i} for i in df.columns],
    page_size=10,
    style_table=table_style,
    style_cell=cell_style,
    style_header=header_style,
    fixed_rows={"headers": True},
    ),
    html.Hr(),
    ]
    )
    )
    return saved_files


    def parse_contents(contents, filename, date):
    """Save and parse the uploaded file."""
    # Save the file to the server and get its path
    file_path = save_file(contents, filename)

    decoded = base64.b64decode(contents.split(",")[1])
    try:
    if filename.endswith(".csv"):
    df = pd.read_csv(io.StringIO(decoded.decode("utf-8")))
    elif filename.endswith(".xls") or filename.endswith(".xlsx"):
    df = pd.read_excel(io.BytesIO(decoded))
    except Exception as e:
    print(e)
    return html.Div(["There was an error processing this file."])

    return html.Div(
    [
    html.Div(
    className="flex",
    children=[
    html.H5(filename),
    html.Div(f"File {filename} saved successfully at {file_path}."),
    ],
    ),
    html.H6(datetime.datetime.fromtimestamp(date)),
    dash_table.DataTable(
    df.to_dict("records"),
    [{"name": i, "id": i} for i in df.columns],
    page_size=10,
    style_table=table_style,
    style_cell=cell_style,
    style_header=header_style,
    fixed_rows={"headers": True},
    ),
    html.Hr(),
    html.Div("Raw Content"),
    html.Pre(
    contents[0:200] + "...",
    style={"whiteSpace": "pre-wrap", "wordBreak": "break-all"},
    ),
    ]
    )


    def delete_file(filename):
    """Delete the selected file from the upload directory."""
    file_path = os.path.join(upload_directory, filename)
    if os.path.exists(file_path):
    os.remove(file_path)
    print(f"File {filename} deleted.")
    else:
    print(f"File {filename} not found.")


    @callback(
    Output("output-data-upload", "children"),
    Input("upload-data", "contents"),
    State("upload-data", "filename"),
    State("upload-data", "last_modified"),
    Input({"type": "delete-button", "index": ALL}, "n_clicks"),
    State({"type": "delete-button", "index": ALL}, "index"),
    )
    def update_output(list_of_contents, list_of_names, list_of_dates, delete_clicks, delete_filenames):
    ctx = callback_context
    triggered = ctx.triggered

    # Handle file deletion
    if triggered and "delete-button" in triggered[0]["prop_id"]:
    for i, n_clicks in enumerate(delete_clicks):
    if n_clicks > 0:
    filename_to_delete = delete_filenames

    # Debugging: Ensure filename is passed
    if filename_to_delete is not None:
    print(f"Attempting to delete file: {filename_to_delete}")
    delete_file(filename_to_delete)
    else:
    print("Filename is None, skipping deletion")
    break # Ensure we only delete one file per click

    # Display saved files or newly uploaded files
    if list_of_contents is not None:
    children = [parse_contents(c, n, d) for c, n, d in zip(list_of_contents, list_of_names, list_of_dates)]
    return children
    else:
    return load_saved_files()

    Continue reading...

Compartilhe esta Página