changeset 2023:e0b7b2a8b914

support generation of ZIP archives in the presence of authorization tokens
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 03 Dec 2022 21:00:36 +0100
parents 96d20b42e740
children e24e93418061 8ff083f67628
files Applications/StoneWebViewer/NEWS Applications/StoneWebViewer/WebApplication/app.js Applications/StoneWebViewer/WebApplication/index.html
diffstat 3 files changed, 88 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/StoneWebViewer/NEWS	Sat Dec 03 17:42:12 2022 +0100
+++ b/Applications/StoneWebViewer/NEWS	Sat Dec 03 21:00:36 2022 +0100
@@ -10,6 +10,7 @@
 * New URL argument "menu" to change the layout of the list of studies/series
 * The first series to be loaded is now automatically opened
 * Annotations are grouped into one submenu for narrow screens
+* Support generation of ZIP archives in the presence of authorization tokens
 * Fix measurement of arcs
 * Width of the vertical slider has doubled to ease user interactions
 * Patient sex is displayed in the top-left information panel
--- a/Applications/StoneWebViewer/WebApplication/app.js	Sat Dec 03 17:42:12 2022 +0100
+++ b/Applications/StoneWebViewer/WebApplication/app.js	Sat Dec 03 21:00:36 2022 +0100
@@ -53,6 +53,9 @@
 var MOUSE_TOOL_CREATE_TEXT_ANNOTATION = 12;  // New in 2.4
 var MOUSE_TOOL_MAGNIFYING_GLASS = 13;        // New in 2.4
 
+var hasAuthorizationToken = false;
+var axiosHeaders = {};
+
 
 function getParameterFromUrl(key) {
   var url = window.location.search.substring(1);
@@ -151,6 +154,45 @@
 }
 
 
+function TriggerDownloadFromUri(uri, filename, mime)
+{
+  if (hasAuthorizationToken) {
+    axios.get(uri, {
+      headers: axiosHeaders,
+      responseType: 'arraybuffer'
+    })
+      .then(function(response) {
+        const blob = new Blob([ response.data ], { type: mime });
+        const url = URL.createObjectURL(blob);
+
+        //window.open(url, '_blank');
+
+        // https://stackoverflow.com/a/19328891
+        var a = document.createElement("a");
+        document.body.appendChild(a);
+        a.style = "display: none";
+        a.href = url;
+        a.download = filename;
+        a.click();
+        window.URL.revokeObjectURL(url);
+      });
+
+  } else {
+    // This version was used in Stone Web viewer <= 2.4, but doesn't
+    // work with authorization headers
+    
+    /**
+     * The use of "window.open()" below might be blocked (depending on
+     * the browser criteria to block popup).  As a consequence, we
+     * prefer to set "window.location".
+     * https://www.nngroup.com/articles/the-top-ten-web-design-mistakes-of-1999/
+     **/
+    // window.open(uri, '_blank');
+    window.location.href = uri;
+  }
+}
+
+
 /**
  * The "mousemove" and "mouseup" events were added in Stone Web viewer
  * 2.5 to allow click/drag on the vertical scrollbar.
@@ -280,19 +322,33 @@
         this.videoUri = '';
         if (this.globalConfiguration.OrthancApiRoot) {
           var that = this;
-          axios.post(that.globalConfiguration.OrthancApiRoot + '/tools/find',
-                     {
-                       Level : 'Instance',
-                       Query : {
-                         StudyInstanceUID: studyInstanceUid
-                       }
-                     })
+          axios.post(that.globalConfiguration.OrthancApiRoot + '/tools/find', {
+            Level : 'Instance',
+            Query : {
+              StudyInstanceUID: studyInstanceUid
+            }
+          }, {
+            headers: axiosHeaders
+          })
             .then(function(response) {
               if (response.data.length != 1) {
                 throw('');
               }
               else {
-                that.videoUri = that.globalConfiguration.OrthancApiRoot + '/instances/' + response.data[0] + '/frames/0/raw';
+                var uri = that.globalConfiguration.OrthancApiRoot + '/instances/' + response.data[0] + '/frames/0/raw';
+
+                if (hasAuthorizationToken) {
+                  axios.get(uri, {
+                    headers: axiosHeaders,
+                    responseType: 'arraybuffer'
+                  })
+                    .then(function(response) {
+                      const blob = new Blob([ response.data ]);
+                      that.videoUri = URL.createObjectURL(blob);
+                    });
+                } else {
+                  that.videoUri = uri;
+                }
               }
             })
             .catch(function(error) {
@@ -1160,22 +1216,16 @@
           this.archiveJob.length > 0) {      
 
         var that = this;
-        axios.get(that.globalConfiguration.OrthancApiRoot + '/jobs/' + that.archiveJob)
+        axios.get(that.globalConfiguration.OrthancApiRoot + '/jobs/' + that.archiveJob, {
+          headers: axiosHeaders
+        })
           .then(function(response) {
             console.log('Progress of archive job ' + that.archiveJob + ': ' + response.data['Progress'] + '%');
             var state = response.data['State'];
             if (state == 'Success') {
               that.creatingArchive = false;
               var uri = that.globalConfiguration.OrthancApiRoot + '/jobs/' + that.archiveJob + '/archive';
-
-              /**
-               * The use of "window.open()" below might be blocked
-               * (depending on the browser criteria to block popup).
-               * As a consequence, we prefer to set "window.location".
-               * https://www.nngroup.com/articles/the-top-ten-web-design-mistakes-of-1999/
-               **/
-              // window.open(uri, '_blank');
-              window.location = uri;
+              TriggerDownloadFromUri(uri, that.archiveJob + '.zip', 'application/zip');
             }
             else if (state == 'Running') {
               setTimeout(that.CheckIsDownloadComplete, 1000);
@@ -1197,7 +1247,9 @@
       console.log('Creating archive for study: ' + studyInstanceUid);
 
       var that = this;
-      axios.post(this.globalConfiguration.OrthancApiRoot + '/tools/lookup', studyInstanceUid)
+      axios.post(this.globalConfiguration.OrthancApiRoot + '/tools/lookup', studyInstanceUid, {
+        headers: axiosHeaders
+      })
         .then(function(response) {
           if (response.data.length != 1) {
             throw('');
@@ -1216,12 +1268,13 @@
               // ZIP streaming is available (this is Orthanc >=
               // 1.9.4): Simply give the hand to Orthanc
               event.preventDefault();
-              window.location.href = uri;
-
+              TriggerDownloadFromUri(uri, orthancId + '.zip', 'application/zip');
             } else {
               // ZIP streaming is not available: Create a job to create the archive
               axios.post(uri, {
                 'Asynchronous' : true
+              }, {
+                headers: axiosHeaders
               })
                 .then(function(response) {
                   that.creatingArchive = true;
@@ -1431,9 +1484,20 @@
   // Bearer token is new in Stone Web viewer 2.0
   var token = getParameterFromUrl('token');
   if (token !== undefined) {
+    hasAuthorizationToken = true;
     stone.AddHttpHeader('Authorization', 'Bearer ' + token);
+    axiosHeaders['Authorization'] = 'Bearer ' + token;
   }
 
+  if (app.globalConfiguration.OrthancApiRoot) {
+    axios.get(app.globalConfiguration.OrthancApiRoot + '/system', {
+      headers: axiosHeaders
+    })
+      .then(function (response) {
+        app.orthancSystem = response.data;
+      });
+  }
+  
 
   /**
    * Calls to "stone.XXX()" can be reordered after this point.
@@ -1604,13 +1668,6 @@
         .catch(function (error) {
           alert('Cannot load the WebAssembly framework');
         });
-
-      if (app.globalConfiguration.OrthancApiRoot) {
-        axios.get(app.globalConfiguration.OrthancApiRoot + '/system')
-          .then(function (response) {
-            app.orthancSystem = response.data;
-          });
-      }
     })
     .catch(function (error) {
       alert('Cannot load the configuration file');
--- a/Applications/StoneWebViewer/WebApplication/index.html	Sat Dec 03 17:42:12 2022 +0100
+++ b/Applications/StoneWebViewer/WebApplication/index.html	Sat Dec 03 21:00:36 2022 +0100
@@ -36,6 +36,7 @@
             <h3>Versions</h3>
             <p>
               Stone Web viewer: {{ stoneWebViewerVersion }} <br/>
+              <span v-if="orthancSystem.Version">Orthanc: {{ orthancSystem.Version }} <br/></span>
               Emscripten compiler: {{ emscriptenVersion }}
             </p>
           </div>
@@ -74,6 +75,7 @@
             <h3>Versions</h3>
             <p>
               Stone Web viewer: {{ stoneWebViewerVersion }} <br/>
+              <span v-if="orthancSystem.Version">Orthanc: {{ orthancSystem.Version }} <br/></span>
               Emscripten compiler: {{ emscriptenVersion }}
             </p>
             <h3>User preferences</h3>