0

I'm trying to convert a HTML file to BytesIO so that I don't need to write the file in the filesystem and get it from memory instead. I've read this about converting image to BytesIO however I can't apply it to HTML file.

I'm using Flask as my framework.

What i have tried:

buffer = io.BytesIO()

merged_df.to_html(buffer, encoding = 'utf-8', table_uuid = 'seasonality_table')
buffer.seek(0)
html_memory = base64.b64encode(buffer.getvalue())

return render_template('summary_01.html', html_data = html_memory.decode('utf-8'))

then in the HTML code which I want to output the html file:

<img id="picture" src="data:html;base64, {{ html_data }}">

Error message I got = TypeError: expected str, bytes or os.PathLike object, not _io.BytesIO

2
  • I don't understand how you want to display HTML as image <img>. It is totally wrong idea. You should put HTML directly without <img> - ie. {{ html_data | safe }} Commented Oct 26, 2022 at 12:20
  • you have to read data - html_memory.read().decode(...). But frankly you can get HTML without using file - simply html = merged_df.to_html() without filename nor buffer Commented Oct 26, 2022 at 12:22

1 Answer 1

1

First: using <img> to display HTML is totally wrong idea.
Tag <img> is only for images like PNG, JPG, etc.

You can get directly HTML using to_html() without filename

html = merged_df.to_html(table_id='seasonality_table')

and send this as HTML

return render_template('summary_01.html', html_data=html)

and you need safe to display it as HTML

{{ html_data | safe }}

BTW:

If you want to put data as file for downloading then you should use <a> instead of <img> and it may need application/octet-stream instead of html to start downloading it.

html = merged_df.to_html(table_id='seasonality_table')
html = base64.b64encode(html.encode('utf-8')).decode('utf-8')

return render_template('summary_01.html', html_data=html)
<a href="data:application/octet-stream;base64,{{ html_data }}">DOWNLOAD</a>

Minimal working example

from flask import Flask, render_template_string
import pandas as pd
import base64

app = Flask(__name__)

@app.route('/')
def index():

    data = {
        'A': [1,2,3], 
        'B': [4,5,6], 
        'C': [7,8,9]
    }

    df = pd.DataFrame(data)

    html = df.to_html(table_id='seasonality_table')
    
    html_base64 = base64.b64encode(html.encode()).decode()
    
    return render_template_string('''<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>

{{ html_data | safe }}

<a href="data:application/octet-stream;base64,{{ html_base64 }}">DOWNLOAD</a>

</body>
</html>''', html_data=html, html_base64=html_base64)


if __name__ == '__main__':
    #app.debug = True 
    #app.run(threaded=False, processes=3)
    #app.run(use_reloader=False)
    app.run()
Sign up to request clarification or add additional context in comments.

3 Comments

OMG it works! yes you're right we can just use to_html() without a filename. A follow up question: the format I set using Pandas styler looks to be gone using this method. Any idea why?
I don't remeber details but it may need to assign styled data frame to variable styled_df and use styled_df.to_html() to get HTML from styles dataframe. Similar problem was few weeks ago in some question on Stackoverflow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.