pythonpandasbytesio

convert html file to BytesIO then pass as Flask variable


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


Solution

  • 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()