From 223cd56105172e973c90f0a06f7e20527b384e50 Mon Sep 17 00:00:00 2001 From: mickare Date: Thu, 18 Mar 2021 17:49:06 +0100 Subject: [PATCH 1/3] add optionial gzip compression in html export Exporting big 3d meshes resulted in huge files since the data is stored as plain text in the html file. By storing the data in compressed base64 the file size can be reduced by 85%. Reduction Examples: 96.8mb to 15.4mb 42.2mb to 2.7mb 27.6mb to 6.8mb --- .../python/plotly/plotly/basedatatypes.py | 4 ++ packages/python/plotly/plotly/io/_html.py | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/packages/python/plotly/plotly/basedatatypes.py b/packages/python/plotly/plotly/basedatatypes.py index 7954dea37f..7970af8c8e 100644 --- a/packages/python/plotly/plotly/basedatatypes.py +++ b/packages/python/plotly/plotly/basedatatypes.py @@ -3672,6 +3672,10 @@ def write_html(self, *args, **kwargs): validate: bool (default True) True if the figure should be validated before being converted to JSON, False otherwise. + compress: bool (default False) + If True, the figure data is compressed reducing the total file size. + It adds an external compression library which requires an active + internet connection. auto_open: bool (default True If True, open the saved file in a web browser after saving. This argument only applies if `full_html` is True. diff --git a/packages/python/plotly/plotly/io/_html.py b/packages/python/plotly/plotly/io/_html.py index cb90de32f9..87dddc1d5c 100644 --- a/packages/python/plotly/plotly/io/_html.py +++ b/packages/python/plotly/plotly/io/_html.py @@ -2,6 +2,8 @@ import json import os import webbrowser +import base64 +import gzip import six @@ -35,6 +37,7 @@ def to_html( default_width="100%", default_height="100%", validate=True, + compress=False, ): """ Convert a figure to an HTML string representation. @@ -121,6 +124,10 @@ def to_html( validate: bool (default True) True if the figure should be validated before being converted to JSON, False otherwise. + compress: bool (default False) + If True, the figure data is compressed reducing the total file size. + It adds an external compression library which requires an active + internet connection. Returns ------- str @@ -230,8 +237,26 @@ def to_html( # Serialize config dict to JSON jconfig = json.dumps(config) + # Compress `jdata` via fflate, and replace `jdata` with a JavaScript variable + script_compress = "" + if compress: + compressed_data = base64.b64encode(gzip.compress(jdata.encode('utf-8'))).decode('ascii'); + script_compress = """\ + const data_compr_b64 = "{compressed_data}"; + const data_raw = fflate.decompressSync( + fflate.strToU8(atob(data_compr_b64), true) + ); + const data = JSON.parse(fflate.strFromU8(data_raw)); + """.format( + compressed_data=compressed_data + ) + # Replace the plotly data with the variable "data". + jdata = "data" + + script = """\ if (document.getElementById("{id}")) {{\ + {script_compress}\ Plotly.newPlot(\ "{id}",\ {data},\ @@ -241,6 +266,7 @@ def to_html( }}""".format( id=plotdivid, data=jdata, + script_compress=script_compress, layout=jlayout, config=jconfig, then_addframes=then_addframes, @@ -300,6 +326,12 @@ def to_html( win_config=_window_plotly_config, plotlyjs=get_plotlyjs() ) + # Add compression library when compression is enabled + load_fflatejs = "" + if compress: + load_fflatejs = "" + + # ## Handle loading/initializing MathJax ## include_mathjax_orig = include_mathjax if isinstance(include_mathjax, six.string_types): @@ -343,6 +375,7 @@ def to_html(
\ {mathjax_script}\ {load_plotlyjs}\ + {load_fflatejs}\
\ " - + load_fflatejs = '' # ## Handle loading/initializing MathJax ## include_mathjax_orig = include_mathjax @@ -532,7 +532,7 @@ def write_html( JSON, False otherwise. compress: bool (default False) If True, the figure data is compressed reducing the total file size. - It adds an external compression library which requires an active + It adds an external compression library which requires an active internet connection. auto_open: bool (default True If True, open the saved file in a web browser after saving.