0

I'm trying to implement a fastapi app with python and to pack the app in a docker container. I'm new with fastapi and also with docker, so I apologize if my question seems not relevant.

The goal is to upload a csv file from my local computer, to interactively process the data frame and to return a processed data frame. After that I would like to be able to save the processed csv file to my computer. The app is located within a docker container.

Until now I was able to:

  1. upload the csv file : I use the uploadFile method to upload the file
@app.get("/")
async def main(request : Request):
    return templates.TemplateResponse("loadFile.html", {"request": request, "title": "Home"})

with the following template:

    <body>
        <form action="/uploadfile" enctype="multipart/form-data" method="post">
        <input name="file" type="file" unique>
        <input type="submit">
        </form>
    </body>
  1. Then I print the data file and I process it (I will not reproduce all the code here)
    @app.post("/uploadfile")
    async def create_upload_files(request: Request, file: UploadFile = File(...)):
         full_path = os.path.abspath(file.filename)
         global DIR_PATH
         DIR_PATH = os.path.dirname(full_path)

         global df # store the data frame as a global variable
         df = pd.read_csv(file.file, sep=';')
         [COLUMNS.append(c) for c in df.columns if c not in COLUMNS and c not in COLUMNS_DISCARDED]
    
         return templates.TemplateResponse("printFile.html",
                                           {"request": request, "title": "Home",
                                            "columns":COLUMNS, 
                                            "columns_discarded": COLUMNS_DISCARDED})
  1. Finally, after having processed the data frame I would like to save the processed csv to my local computer. In development mode it works when I do as following:
@app.post("/quit")
async def quit_and_save(request: Request):
  -- do some stuff--
  # How I do at this time...
  df.to_csv(os.path.join(DIR_PATH,'df_data.csv'))
  print("Table saved to: {}".format(DIR_PATH))

I embedded the app within a docker container withe the Dockerfile

FROM python:3.9-slim-buster

# 
WORKDIR /code

# 
COPY ./requirements.txt /code/requirements.txt
COPY ./static /code/static
COPY ./templates /code/templates
# 
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

# 
COPY ./main.py /code/

# 
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "30"]

So Finally, when I run the app locally in dev mode I'm able to process the data frame and when I go to /quit, I obtain a df_data.csv. However I don't know how to do it with docker. At this time, in the Docker console I've got the message:

Table saved to: /code

Ideally I would like to have a pop-up window asking where I want to save the file or if it is too complicated, another soution would be that the df_data would be saved within the same folderthan the initial .csv

After finishing the development phase, I would like to deploy online the app so that other people would be able to use the app.

I would be very grateful if you could help me

Best regards

Xavier

Xavier
  • 61
  • 1
  • 2
  • I'd probably write this with an `@app.get()` route that returns the CSV file. Then you can retrieve it using an ordinary `curl` command. That will work whether or not the server runs in a container, and it will work even if you can't log into the server hosting it. – David Maze Feb 23 '22 at 14:12
  • 1
    You can use FastAPIs FileResponse or StreamingResponse to serve a file or content back to the browser as a file to download: https://fastapi.tiangolo.com/advanced/custom-response/#fileresponse - storing the file inside a Docker container means that you would probably want to consider how you're using a volume and how you're going to clean it up - if the file is just temporary. You can also mount a local directory at a location inside your container, so that any file written there becomes visible (and permanent) on your local filesystem. But a proper response is the way to go usually. – MatsLindh Feb 23 '22 at 14:50
  • Thank you for your kind answer, I tried to implement your solution with a new method: @app.get('/download') async def dl_files(request : Request, response_class=FileResponse): print(os.getcwd()) return df_data.to_csv('df_data.csv') However, with docker I still downlad the file in the /code folder and not directly to my computer. Would you have any suggestion ? – Xavier Feb 23 '22 at 15:53
  • 1
    You should do `return FileResponse` from your view function with an appropriate content type and the content of the file from df_data.to_csv() – MatsLindh Feb 23 '22 at 16:17
  • [This](https://stackoverflow.com/a/71205127/17865804) also might be of help. – Chris Feb 23 '22 at 20:44

0 Answers0