Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Handling Images on the Frontend Using FastAPI
Sachin
Sachin

Posted on • Originally published atgeekpython.in

     

Handling Images on the Frontend Using FastAPI

In this tutorial, we'll look at how to use FastAPI to display static and dynamic images on the frontend.

Displaying images on the frontend can be a time-consuming operation; it takes a significant amount of time and effort to create logic to show static and dynamic images. FastAPI includes certain classes and modules that can help you save time and effort when displaying images.

Displaying static images

If you've dealt with the Python Flask or Django web frameworks, you'll know that in order to serve static files, we need to include them in the static folder established within the project's root directory.

The procedure is the same, however, the logic for displaying static images in FastAPI differs.

The following code will help us to display thestatic images on the frontend.

# static_img.pyfromfastapiimportFastAPIfromfastapi.responsesimportHTMLResponsefromfastapi.staticfilesimportStaticFilesapp=FastAPI()app.mount("/imgs",StaticFiles(directory="imgs"),name='images')@app.get("/",response_class=HTMLResponse)defserve():return"""    <html>        <head>            <title></title>        </head>        <body>        <img src="imgs/g.png">        <h1>Hello World</h1>        </body>    </html>"""
Enter fullscreen modeExit fullscreen mode

To serve static images or files, we utilised FastAPI'sStaticFiles class. This class is derived directly from Starlette; we can simply import that class fromfastapi.staticfiles instead ofstarlette.staticfiles for convenience.

We stored our static image inside theimgs directory present in the root directory and we passed this directory to theStaticFiles() instance andmounted it in the/imgs path.

Mounting here means setting up or adding a completely independent application in a specific path, which will then take care of handling all the sub-paths.

Here,

/img - is a sub-path on which the sub-application will be mounted.

directory='img' - refers to the static directory where our static images or files will be stored.

name='images' - this name will be used by FastAPI internally or we can skip this also.

The path operation decorator@app.get("/", response class=HTMLResponse) was then created, and you'll notice that we passedHTMLResponse, which will assist in returning the HTML response directly from FastAPI.

Theresponse_class will also be used to define themedia type of the response and in this case, in the HTTP header,Content-Type will be set totext/html.

Then we created apath operation function calledserve() and returned the HTML in which we passed our static image path("imgs/g.png") in thesrc attribute of the<img> tag.

Now run the server using the uvicorn.

uvicornstatic_img:app--reload
Enter fullscreen modeExit fullscreen mode

Here's the API response

API response

If we see the API response in the Postman, then we'll see a raw HTML as a response by the FastAPI.

API response in the Postman

Due toHTMLResponse in the path operation decorator, the browser parses our HTML like it usually does for any HTML file.

Another approach

This approach might be beneficial if you are working on a serious project and want your code to be more readable and manageable.

In this approach, we'll be usingjinja and instead of usingHTMLResponse we'll be usingJinja2Templates to render the HTML response.

In order to use theJinja2Templates, we need to install thejinja2 library and it can be installed using the pip by running the commandpip install jinja2.

# files.pyfromfastapiimportFastAPI,Request# The modules are directly coming from starlettefromfastapi.staticfilesimportStaticFilesfromfastapi.templatingimportJinja2Templatesapp=FastAPI()app.mount("/static",StaticFiles(directory="static"),name="static")templates=Jinja2Templates(directory="templates")@app.get("/")defstatic(request:Request):returntemplates.TemplateResponse("index.html",{"request":request})
Enter fullscreen modeExit fullscreen mode

The process is pretty much similar to the first approach but in this approach, we imported some more classes such asRequest andJinja2Templates from thefastapi andfastapi.templating modules, respectively.

Like in the first approach, we mounted theStaticFiles(directory="static") instance in a path/static.

Then using theJinja2Templates(directory="templates"), we specified the directory calledtemplates from where the FastAPI will look for the.html files and stored them inside thetemplates variable.

Then we created the path operation decorator@app.get("/") and followed by it created the path operation function calledstatic and passed theRequest class to the parameterrequest.

Then we returned theTemplateResponse("index.html", {"request": request}). In this case, we passed therequest as part of the key-value pairs in theJinja2 context. This will allow us to inject the dynamic content that we desire when the template is rendered.

Now write HTML code in theindex.html file inside thetemplates directory.

<html><head><linkhref="{{ url_for('static') }}"/><title>Serving Image Files Using FastAPI</title></head><body><imgsrc="{{ url_for('static', path='assets/GP.png') }}"/></body></html>
Enter fullscreen modeExit fullscreen mode

Just add the code<link href="{{ url_for('static') }}" /> to link the directory namedstatic as shown in the above code.

Then in thesrc attribute of the<img> tag, we specified the path to the static image using jinja like this{{ url_for('static', path='assets/GP.png') }}.

Folder structure of static directory

Now run the server using the commanduvicorn files:app --reload.

Here's the response

API response using templates

If we see what we get when we send the request to the API using Postman.

API response in Postman

We can include the same HTML as above in ourindex.html and get the same result but it won't be a good practice at all.

Serving user-provided images

In this approach, we'll have a form where the user can enter an image that will be displayed on the frontend.

When a user uploads an image file, it is sent asform data, and we must install the following library to receive it.

pipinstallpython-multipart
Enter fullscreen modeExit fullscreen mode

The following code will be responsible for uploading and displaying the user-provided image.

# dynamic.pyfromfastapiimportFastAPI,UploadFile,File,Requestfromfastapi.templatingimportJinja2Templatesimportbase64app=FastAPI()templates=Jinja2Templates(directory="templates")@app.get("/")defdynamic_file(request:Request):returntemplates.TemplateResponse("dynamic.html",{"request":request})@app.post("/dynamic")defdynamic(request:Request,file:UploadFile=File()):data=file.file.read()file.file.close()# encoding the imageencoded_image=base64.b64encode(data).decode("utf-8")returntemplates.TemplateResponse("dynamic.html",{"request":request,"img":encoded_image})
Enter fullscreen modeExit fullscreen mode

The classUploadFile and functionFile from fastapi were imported into the code above to assist in handling the reading and uploading of the image file. We imported thebase64 library to handle image encoding and decoding.

We created a path operation decorator (@app.get("/")) and right below it created a path operation function calleddynamic_files that will render thedynamic.html file on the path"/".

Then we created a path operation decorator(@app.post("/dynamic")) to handle thePost request and then we created a path operation function calleddynamic and passedrequest: Request andfile: UploadFile = File(). Then we read the image file and stored it inside thedata variable and finally closed the file.

Here,file.file.read() is equivalent toUploadFile.file.read().UploadFile has afile attribute which is a file-like object andread() is a method also provided byUploadFile to read the bytes/characters of the image.

If we would have defined theasynchronous path operation function, then we could read the file usingawait file.read().

Now we've read the bytes of the image file and it needs to be encoded in a string that can be returned and passed to the template. If we look at the image's bytes, it would look like the following.

xbd\x02\xacf\xb6\xaa\x02\x889\x95\xac6Q\x80\xa4<1\xcd\xef\xf7R\xc2\xb2<j\x08&6\xa8.s\x16M!i\xa8#\xe7RM$\x15\x00\x84\x81...x00\x00P\x1d\x01\x04\x00\x00\x00\x00\x00\xa8\x8e\x00\x02\x00\x00\x00\x00\x00T\xe7\xff\x03a\xbc\xbee\x93\xf6V\xfc\x00\x00\x00\x00IEND\xaeB`\x82'
Enter fullscreen modeExit fullscreen mode

encoded_image = base64.b64encode(data).decode("utf-8") will encode the bytes of the image file stored inside thedata variable using theutf-8 encoding into a string and the encoded string will be stored inside theencoded_image variable. Now, if we examine the encoded string, they will all appear to be random characters and resemble the following.

+jYs7u5Zhy29PmXSh8aQtPim5Y4rC0OKzTQj5RYpzj2IBBCw3a7A0nEMRI1IbLj+uYSjUq/60lOuN3uaNuWvu85WK/RlHj67JyuW/H04oL16hCdtjvx6PFTD...I4AAAAAAAADVEUAAAAAAAIDqCCAAAAAAAEB1BBAAAAAAAKA6AggAAAAAAFAdAQQAAAAAAKiOAAIAAAAAAFTn/wNhvL5lk/ZW/AAAAABJRU5ErkJggg==
Enter fullscreen modeExit fullscreen mode

Then we returned thedynamic.html file and passed the variableencoded_image as a value of the key"img".

Writing template

dynamic.html file

<html><head><title>Rendering Dynamic Images Using FastAPI</title></head><body><formaction="/dynamic"enctype="multipart/form-data"method="POST"><inputname="file"type="file"/><inputtype="submit"/></form>    {% if img %}<h1>Rendered Image</h1><imgsrc="data:image/jpeg;base64,{{ img }}"/>    {% else %}<h1>Image will be render here...</h1>    {% endif %}</body></html>
Enter fullscreen modeExit fullscreen mode

In ourdynamic.html file, we added a form tag that handles aPOST request from the"/dynamic" URL, and we used theenctype attribute with the value"multipart/form-data" to handle file uploading through the form. Then, within the form, we added twoinput tags: one for selecting the image and one for submitting it.

Then we used jinja syntax to create anif-else condition and inserted animg tag with asrc attribute containing our image. We passed"data:image/jpeg;base64, img" because we need to use this format to display base64 images in HTML.

Testing API

Go to the URL127.0.0.1:8000.

File selected for rendering

We chose the image that will be displayed. The image will be displayed if we click the submit button.

Image displayed

What if we want to save the user-provided image in a particular folder?

Saving user-provided images

To save user-provided images in a specific folder, assume we have a folder calleduploads and want to save the images there.

# dynamic.pyfromfastapiimportFastAPI,UploadFile,File,Requestfromfastapi.templatingimportJinja2Templatesimportbase64app=FastAPI()templates=Jinja2Templates(directory="templates")@app.get("/")defdynamic_file(request:Request):returntemplates.TemplateResponse("dynamic.html",{"request":request})@app.post("/dynamic")defdynamic(request:Request,file:UploadFile=File()):data=file.file.read()# Image will be saved in the uploads folder prefixed with uploaded_withopen("uploads/saved_"+file.filename,"wb")asf:f.write(data)file.file.close()# encoding and decoding the image bytesencoded_image=base64.b64encode(data).decode("utf-8")returntemplates.TemplateResponse("dynamic.html",{"request":request,"img":encoded_image})
Enter fullscreen modeExit fullscreen mode

We used theopen() function and passed the path to ouruploads folder with the name we want to prefix with the name of the image and opened it inwrite mode and then usedf.write(data) to create an image within the uploads folder with the namesaved_xyz.png.

Testing

Run the server usinguvicorn dynamic:app --reload and go to the URL127.0.0.1:8000.

Image name to be saved and displayed

Image displayed

Image saved at the destination folder

Conclusion

If you have worked with the Flask web framework, you may find it similar. FastAPI is a modern, high-performance web framework for building APIs using Python.

In this article, we've learned to display the static and user-provided(dynamic) images on the frontend using certain classes and modules from FastAPI. We saw two approaches for displaying static files on the frontend using FastAPI and then saw the process for displaying user-provided images and then the process for saving them in a particular folder.

Through this, we came across responses in FastAPI, requesting files, reading and uploading files, jinja templates and handling static files.


🏆Other articles you might be interested in if you liked this one

Display static and dynamic images on the frontend using Flask.

Get started with FastAPI - A beginner guide.

Build your first command line interface using Python.

Learn how to execute the dynamically generated code using Python.

Public, Protected and Private access modifiers in Python.

Perform high-level file operation using shutil in Python.

Extract information from the web pages using Python and BeautifulSoup.


That's all for now

Keep Coding✌✌

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

A Python developer obsessed with Machine Learning and Data Science.
  • Location
    Delhi
  • Joined

More fromSachin

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp