flet icon indicating copy to clipboard operation
flet copied to clipboard

Additional parameter for `flet.fastapi.app` to customize `upload_endpoint_path`

Open timok19 opened this issue 1 year ago • 2 comments

Make upload_endpoint_path customizable from flet.fastapi.app

Current implementation of the Flet app with FastAPI support does not allow to add custom endpoint for uploading files from FilePicker component. It is only possible via specific environment variable. In that case there is no flexibility.

Solution

  • By adding an additional parameter upload_endpoint_path to the app() function in the flet.fastapi and providing it to the FletApp() instance will solve the problem.
  • This will not affect the flow of the application and add one more possibility to setup the upload_endpoint_path from the FastAPI main

Example of the change

def app(
    session_handler: Union[Callable[[Page], Awaitable], Callable[[Page], None]],
    proxy_path: Optional[str] = None,
    assets_dir: Optional[str] = None,
    app_name: Optional[str] = None,
    app_short_name: Optional[str] = None,
    app_description: Optional[str] = None,
    web_renderer: WebRenderer = WebRenderer.CANVAS_KIT,
    use_color_emoji: bool = False,
    route_url_strategy: str = "path",
    upload_dir: Optional[str] = None,
    upload_endpoint_path: Optional[str] = None,  # Added there
    max_upload_size: Optional[int] = None,
    secret_key: Optional[str] = None,
    session_timeout_seconds: int = DEFAULT_FLET_SESSION_TIMEOUT,
    oauth_state_timeout_seconds: int = DEFAULT_FLET_OAUTH_STATE_TIMEOUT,
):
...

    fastapi_app = FastAPI()

    @fastapi_app.websocket(f"/{websocket_endpoint}")
    async def app_handler(websocket: WebSocket):
        await FletApp(
            asyncio.get_running_loop(),
            session_handler,
            session_timeout_seconds=session_timeout_seconds,
            oauth_state_timeout_seconds=oauth_state_timeout_seconds,
            upload_endpoint_path=upload_endpoint_path,  # Added there
            secret_key=secret_key,
        ).handle(websocket)

And also considering to remove an unnecessary if check in this part of the app.py:

    if upload_dir:

        @fastapi_app.put(f"/{upload_endpoint}")
        async def upload_handler(request: Request):
            # if not upload_dir:  <- Remove it, because the top check is present
            #    return
            await FletUpload(
                upload_dir=upload_dir,
                max_upload_size=max_upload_size,

timok19 avatar Mar 22 '24 02:03 timok19

Will you mind opening a PR to share your idea?

ndonkoHenri avatar Mar 26 '24 11:03 ndonkoHenri

Sure, I will open a PR :)

timok19 avatar Mar 26 '24 12:03 timok19

@timok19 , @ndonkoHenri

This is how I am doing it currently. User selected file is uploaded into the dynamically created folder based on user input via variable session_area_path.

@app.put("/upload") async def flet_uploads(request: Request): await FletUpload(session_area_path+"/").handle(request)

if file_picker.result is not None and file_picker.result.files is not None: upload_url="" for f in file_picker.result.files: uf.append( FilePickerUploadFile( f.name, upload_url=page.get_upload_url(f.name, 600), ) ) print(f'upload_url from call to get_upload_url() using {f.name}={upload_url}') pdffile=f.name ## this would work since we are picking up only one file.

        file_picker.upload(uf)

Is this method incorrect?

mxav1111 avatar Mar 27 '24 18:03 mxav1111

@timok19 , @ndonkoHenri

This is how I am doing it currently. User selected file is uploaded into the dynamically created folder based on user input via variable session_area_path.

@app.put("/upload")

async def flet_uploads(request: Request): await FletUpload(session_area_path+"/").handle(request) if file_picker.result is not None and file_picker.result.files is not None: upload_url="" for f in file_picker.result.files: uf.append( FilePickerUploadFile( f.name, upload_url=page.get_upload_url(f.name, 600), ) ) print(f'upload_url from call to get_upload_url() using {f.name}={upload_url}') pdffile=f.name ## this would work since we are picking up only one file.

        file_picker.upload(uf)

Is this method incorrect?

Your method is working and seems ok for the basic purpose, but the topic is about endpoint path modification on backend (FastAPI). What if you want to make a POST request on a specific endpoint? For example, it can be an endpoint that will be generated each time based on a new browser session etc.

timok19 avatar Mar 27 '24 18:03 timok19

@timok19 Got this. Thank you.

mxav1111 avatar Mar 27 '24 22:03 mxav1111