From 27467fa2c8a533cad7da1b0210a0a8d5c1f04757 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sven=20Sch=C3=B6ling?= Date: Fri, 12 Apr 2019 18:13:39 +0200 Subject: [PATCH] kivi.js: kivi.save_file und client_js binding (cherry picked from commit f68ea953a6a563172f12991d2ca3f9f17ad89dd2) --- SL/ClientJS.pm | 1 + js/client_js.js | 1 + js/kivi.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/SL/ClientJS.pm b/SL/ClientJS.pm index a134cad9b..336f97144 100644 --- a/SL/ClientJS.pm +++ b/SL/ClientJS.pm @@ -113,6 +113,7 @@ my %supported_methods = ( # ## other stuff ## redirect_to => 1, # window.location.href = + save_file => 4, # kivi.save_file(, ) flash => 2, # kivi.display_flash(, ) flash_detail => 2, # kivi.display_flash_detail(, ) diff --git a/js/client_js.js b/js/client_js.js index 8be5676e4..9fc14b6c6 100644 --- a/js/client_js.js +++ b/js/client_js.js @@ -151,6 +151,7 @@ ns.eval_json_result = function(data) { // ## other stuff ## else if (action[0] == 'redirect_to') window.location.href = action[1]; + else if (action[0] == 'save_file') kivi.save_file(action[1], action[2], action[3], action[4]); else if (action[0] == 'flash') kivi.display_flash(action[1], action[2]); else if (action[0] == 'flash_detail') kivi.display_flash_detail(action[1], action[2]); else if (action[0] == 'clear_flash') kivi.clear_flash(action[1], action[2]); diff --git a/js/kivi.js b/js/kivi.js index 444892117..a76ad8a99 100644 --- a/js/kivi.js +++ b/js/kivi.js @@ -558,6 +558,39 @@ namespace("kivi", function(ns) { return undefined; }; + ns.save_file = function(base64_data, content_type, size, attachment_name) { + // atob returns a unicode string with one codepoint per octet. revert this + const b64toBlob = (b64Data, contentType='', sliceSize=512) => { + const byteCharacters = atob(b64Data); + const byteArrays = []; + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize); + + const byteNumbers = new Array(slice.length); + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + } + + const blob = new Blob(byteArrays, {type: contentType}); + return blob; + } + + var blob = b64toBlob(base64_data, content_type); + var a = $(""); + var url = window.URL.createObjectURL(blob); + a.attr("href", url); + a.attr("download", attachment_name); + $("body").append(a); + a[0].click(); + window.URL.revokeObjectURL(url); + a.remove(); + } + ns.detect_duplicate_ids_in_dom = function() { var ids = {}, found = false; -- 2.20.1