user3473161
user3473161

Reputation: 327

How can I display a TemporaryUploadedFile from Django in HTML as an image?

In Django, I have programmed a form in which you can upload one image. After uploading the image, the image is passed to another method with the type TemporaryUploadedFile, after executing the method it is given to the HTML page.

What I would like to do is display that TemporaryUploadedFile as an image in HTML. It sounds quite simple to me but I could not find the answer on StackOverflow or on Google to the question: How to display a TemporaryUploadedFile in HTML without having to save it first, hence my question.

All help is appreciated.


Edit 1:

To give some more information about the code and the variables while debugging.

input_image = next(iter(request.FILES.values()))
output_b64 = (input_image.content_type, str(base64.b64encode(input_image.read()), 'utf8'))

Debug information

Upvotes: 0

Views: 2352

Answers (2)

xyres
xyres

Reputation: 21789

Well, you can encode the image to base64 and use a data url as the value for src.

A base64 data url looks like this:

<img src="data:image/png;base64,SGLAFdsfsafsf098sflf">
               \_______/        \__________________/
                   |                     |
                File type        base64 encoded data

Read the Mozilla docs for more on data urls.

Here's some relevant code:

import base64

def my_view(request):
    # assuming `image` is a <TemporaryUploadedFile object>
    
    image_b64 = base64.b64encode(image.read())
    image_b64 = image_b64.decode('utf8') # convert bytes to string
    image_type = image.content_type # png or jpeg or something else
    return render('template', {'image_b64': image_b64, 'image_type': image_type})

Then in your template:

<img src="data:{{ image_type }};base64,{{ image_b64 }}">

Upvotes: 3

user3473161
user3473161

Reputation: 327

I want to thank xyres for pushing me in the right direction. As you can see, I used some parts of his solution in the code below:

# As input I take one image from the form.
temp_uploaded_file = next(iter(request.FILES.values()))

# The TemporaryUploadedFile is converted to a Pillow Image
input_image = pil_image.open(temp_uploaded_file)

# The input image does not have a name so I set it afterwards. (This step, of course, is not mandatory)
input_image.filename = temp_uploaded_file.name

# The image is saved to an InMemoryFile
output = BytesIO()
input_image.save(output, format=img.format)

# Then the InMemoryFile is encoded
img_data = str(base64.b64encode(output.getvalue()), 'utf8')
output_b64 = ('image/' + img.format, img_data)

# Pass it to the template
return render(request, 'visualsearch/similarity_output.html', {
    "output_image": output_b64
})

In the template:

<img id="output_image" src="data:{{ image.0 }};base64,{{ image.1 }}">

The current solution works but I don't think it is perfect because I expect that it can be done with less code and faster, so if you know how this can be done better you are welcome to post your answer here.

Upvotes: 0

Related Questions