Skip to content

Commit 08a157f

Browse files
authored
graph: fix “Download PNG” for large images (#1610)
Summary: When viewing large graphs in Chrome, clicking the “Download PNG” button could the error message, “Failed - Network error”. This is because Chrome does not support downloading large data-URLs. Chrome does, however, support downloading large object URLs, so this patch makes the appropriate change to use that API instead. Test Plan: Generate the `audio_demo` data and open the `wave:01;sine_wave` graph in TensorBoard in Chrome. Transitively expand all node groups. Then, click “Download PNG”. Before this patch, this consistently failed to download. After this patch, it downloads and image with the correct contents. Also tested in Firefox. wchargin-branch: graph-download-png-blob
1 parent 6828714 commit 08a157f

File tree

1 file changed

+18
-1
lines changed
  • tensorboard/plugins/graph/tf_graph_common

1 file changed

+18
-1
lines changed

tensorboard/plugins/graph/tf_graph_common/minimap.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,24 @@ export class Minimap {
155155
let $download = d3.select('#graphdownload');
156156
this.download = <HTMLLinkElement>$download.node();
157157
$download.on('click', d => {
158-
this.download.href = this.downloadCanvas.toDataURL('image/png');
158+
// Revoke the old URL, if any. Then, generate a new URL.
159+
URL.revokeObjectURL(this.download.href);
160+
// We can't use the `HTMLCanvasElement.toBlob` API because it does
161+
// not have a synchronous variant, and we need to update this href
162+
// synchronously. Instead, we create a blob manually from the data
163+
// URL.
164+
const dataUrl = this.downloadCanvas.toDataURL("image/png");
165+
const prefix = dataUrl.slice(0, dataUrl.indexOf(","));
166+
if (!prefix.endsWith(";base64")) {
167+
console.warn(`non-base64 data URL (${prefix}); cannot use blob download`);
168+
this.download.href = dataUrl;
169+
return;
170+
}
171+
const data = atob(dataUrl.slice(dataUrl.indexOf(",") + 1));
172+
const bytes =
173+
new Uint8Array(data.length).map((_, i) => data.charCodeAt(i));
174+
const blob = new Blob([bytes], {type: "image/png"});
175+
this.download.href = URL.createObjectURL(blob);
159176
});
160177

161178
let $svg = d3.select(this.svg);

0 commit comments

Comments
 (0)