Displaying and downloading Resources from GUI

50 views
Skip to first unread message

CataRay

unread,
Jul 9, 2025, 5:51:30 PM7/9/25
to xnat_discussion
Hi XNAT Team,

I am trying to replicate the functionality that the DICOM data has in the GUI, where you can download files.
I tried using as a template the file:
  • xnat-templates/screens/xnat_imageSessionData/xnat_imageSessionData_scans.vm
and created my own:
  • xnat-templates/screens/xnat_imageSessionData/xnat_imageSessionData_resources.vm
Here is the code:

<!-- BTIL -->

<!-- BEGIN /screens/xnat_experimentData/xnat_imageSessiontData_resources.vm -->



## Get all methods

#*#set($methods = $om.getClass().getMethods())

#foreach($method in $methods)

   <p>method: $method.getName()</p>

#end*#


## --------------------------------------------------

  ## Fetch All Resources for the Session

  ## --------------------------------------------------

  #set($resources = $om.getAllResources())


  <script type="text/javascript">

      ## Initialize JavaScript object for managing resource data

      var XNAT                = getObject(XNAT || {});

      XNAT.data               = getObject(XNAT.data || {});

      XNAT.data.context       = getObject(XNAT.data.context || {});

      XNAT.data.context.resources = [];

  </script>



## --------------------------------------------------

## Fetch All Non-DICOM Resources

## --------------------------------------------------

#foreach($resource in $resources)

 #set($label = $!resource.getLabel())


 #if($label == "")

   #set($label = $resource.getXSIType())

 #end

 #if($label != "DICOM" && $label != "SNAPSHOTS" )

   ## --------------------------------------------------

   ## Table for Non-DICOM Resources (e.g., Reports, NIFTI)

   ## Matches Structure in xnat_imageSessionData.vm

   ## --------------------------------------------------


  

   <link rel="stylesheet" href="$content.getURI("scripts/xnat/app/scanTable/scanTable.css")"></link>

   <div class="data-table-container" style="width: #if($siteConfig.uiDisplaySeriesDescription) 1089px #else 889px #end" id="selectable-table-scans">

   <div class="data-table-titlerow">

       <h3 class="data-table-title">$label</h3>


       ## Bulk Action Section

       <div class="data-table-actionsrow">

           <span class="textlink-sm data-table-action">Bulk Actions:</span>


           ## Check if user has permission to download

           #if($user.checkRestrictedFeature("$!om.getProject()","data_download"))

               <button class="btn btn-sm data-table-action do-resource-download disabled">

                   Download

               </button>

           #end


           #addGlobalCustomScreens("xnat_imageSessionData/resourceActions")

       </div>

   </div>


   ## Attempt to load catalog [Cata - Not sure why but without this files are not populated)

   #set($catalogBean = $om.getCatalogBean($resource.getUri))


   ## Example path : http://redlradadm05296.ad.medctr.ucla.edu:8080/xnat/data/experiments/BTIL_XNAT_E00061/resources/237/files/adc_reg.nii.gz


   #set($files =  $resource.getCorrespondingFilesWithCatEntries($resource.getUri))

   #set($stats = $resource.getReadableFileStats())



   #if($files.isEmpty())

       <p><em>No files found in this resource.</em></p>

   #else

       <div class="data-table-wrapper" style="padding-right: 0">

       <table class="xnat-table clean fixed-header selectable">

           <thead>

           <tr>

               <th class="toggle-all" style="width: 45px;">

                   <input type="checkbox" class="selectable-select-all" id="toggle-all-scans" title="Toggle All Scans" />

               </th>

               <th class="left" style="width: 300px;">File Name</th>

               <th class="left" style="width: 100px;">Size</th>

               <th class="left" style="width: 200px;">Date Added</th>

               <th class="left" style="width: 200px;">Note</th>

               <th style="width: 45px;"><span class="run-menu" style="display: none;">Run</span></th>

           </tr>

           </thead>

       <tbody>


           #foreach($filePath in $files)=

           #set($name = $filePath.getName())

           #set ($resourceID =$!filePath.getProperty("createdEventId"))

           #set($date  = $resource.getInsertDate()) ##getLastModified

           ##TODO: Fix Size and  Date| Add Notes| Remove Download and add as scans| Organize alph | Check download | user

           <tr>

               <td class="scan-actions-controls scan-selector center" style="width: 45px;">

                   <input type="checkbox" class="selectable-select-one" name="resourceAction" value="$name" />

               </td>

               <td  style="width: 300px;">$name</td>

               <td  style="width: 100px;">$filePath</td>

               <td  style="width: 200px;">$!date</td>

               <td id="resource-${resourceID}-note">

                   <div class="resource-note-content pull-left text-left" style="width:85%;" title="$!resource.getProperty("note")">

                       <span class="truncate">

                       #if($!resource.getProperty("note"))

                           #escapeCleanHTML($!resource.getProperty("note"))

                       #end

                       </span>

                   </div>

                   #if($item.getStatus()!="obsolete")

                       #if(!$turbineUtils.toBoolean($siteConfig.getProperty("security.prevent-data-deletion","false")) || $siteConfig.getProperty("security.prevent-data-deletion-override","[]").contains($om.getItem().getStatus()))

                           #if ($item.canEdit($user))

                               <div class="inline-actions pull-right text-right" style="width:15%;">

                                   <i class="fa fa-edit edit-resource-note"  data-scan-id="${resourceID}" title="Edit Note"></i>

                               </div>

                           #end

                       #end

                   #end

               </td>

               <td class="run-menu inline-actions-menu-container" style="position: relative; width: 24px; display: none;">

                   <div class="inline-actions-menu-toggle"></div>

                   <ul class="inline-actions-menu single-scan-actions-menu" style="display:none;"></ul>

               </td>

           </tr>

           #end

       </tbody>

       </table>

   </div>

   </div>


   <b>Total:</b> $!stats

   <h3>           .</h3>

   #end

 #end

#end




## --------------------------------------------------

## JavaScript for Table Behavior (from xnat_imageSessionData.vm)

## --------------------------------------------------

<script src="$content.getURI("/scripts/xnat/app/scanTable/scanTable.js")"></script>

<script src="$content.getURI("/scripts/xnat/app/scanTable/selectableTableBehavior.js")"></script>








<!-- END /screens/xnat_experimentData/xnat_imageSessiontData_resources.vm -->



With this code, I am able to see an unsorted list of files, but I can't access any other information about them or download them:

Screen Shot 2025-07-09 at 14.25.03.png

I am able to download the data from the file manager correctly, but not from the session page. 

Screen Shot 2025-07-09 at 14.32.12.png

We just recently started using XNAT and any help understanding what we might be doing incorrectly would be appreciated!

Mohana Ramaratnam

unread,
Jul 10, 2025, 1:43:37 AM7/10/25
to xnat_di...@googlegroups.com
Hello,

A resource (hence all files in the resource) at the experiment level can be downloaded using:

XNAT_HOST/data/projects/PROJECT_ID_HERE/subjects/SUBJECT_ID_HERE/experiments/EXPERIMENT_ID_HERE/resources/RESOURCE_LABEL_HERE/files?format=zip

The URL used by Manage Files is: 

XNAT_HOST/REST/experiments/XNAT_EXP_ID/resources/RESOURCE_ID/files?structure=improved&all=true&format=zip

The download button that you are using has been built around the scan element. If you look into the code here, the download link is set at the scan level and hence your download does not work. 

We would love to know how you are using XNAT, you could schedule a call here:

https://xnatworks.io/contact/ 

Regards,
Mohana Ramaratnam,

 moh...@xnatworks.io
 xnatworks.io | Find us on LinkedIn


--
You received this message because you are subscribed to the Google Groups "xnat_discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xnat_discussi...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/xnat_discussion/9563266a-2add-4489-960f-485a86f9292an%40googlegroups.com.

Timothy Olsen

unread,
Jul 10, 2025, 12:27:06 PM7/10/25
to xnat_di...@googlegroups.com
If you change this:
<td  style="width: 300px;">$name</td>

To this:
               <td  style="width: 300px;"><a href="${SITE_ROOT}/data/experiment/$om.getId()/resources/${label}/files/${name}">$name</a></td>

You should be able to download each file individually.

I'd suggest getting rid of the checkboxes if that isn't required.  And then change the Download button to Download All and use the url Mohana referenced for that one.

Tim


Timothy R Olsen 

Founder, President

CataRay

unread,
Jul 15, 2025, 10:26:48 AM7/15/25
to xnat_discussion
Thank you both for your help.
I managed to make both suggestions work. The only thing pending is to sort the resources alphabetically. 

I tried:
#foreach($file in $files)
  #set($void = $file.setProperty("sortName", $file.getName().toLowerCase()))
#end

#set($sortedFiles = $files.sort("sortName"))


However, sortedFiles is empty. 
Any insight on how to make this work would be appreciated! 
Reply all
Reply to author
Forward
0 new messages