Mercurial > hg > orthanc
changeset 485:bdbde1fbfab3
send resources through HTTP
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 16 Jul 2013 13:48:33 +0200 |
parents | b8ace6fc1d1f |
children | 49aa17c03cd3 |
files | OrthancExplorer/explorer.html OrthancExplorer/explorer.js OrthancServer/OrthancInitialization.cpp OrthancServer/OrthancRestApi.cpp Resources/Configuration.json |
diffstat | 5 files changed, 188 insertions(+), 52 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancExplorer/explorer.html Tue Jul 16 12:51:27 2013 +0200 +++ b/OrthancExplorer/explorer.html Tue Jul 16 13:48:33 2013 +0200 @@ -253,7 +253,12 @@ </div> </div> - <div id="loading" style="display:none;" class="ui-body-c"> + <div id="peer-store" style="display:none;" class="ui-body-c"> + <p align="center"><b>Sending to Orthanc peer...</b></p> + <p><img src="libs/images/ajax-loader2.gif" alt="" /></p> + </div> + + <div id="dicom-store" style="display:none;" class="ui-body-c"> <p align="center"><b>Sending to DICOM modality...</b></p> <p><img src="libs/images/ajax-loader2.gif" alt="" /></p> </div>
--- a/OrthancExplorer/explorer.js Tue Jul 16 12:51:27 2013 +0200 +++ b/OrthancExplorer/explorer.js Tue Jul 16 13:48:33 2013 +0200 @@ -783,6 +783,13 @@ function ChooseDicomModality(callback) { + var clickedModality = ''; + var clickedPeer = ''; + var items = $('<ul>') + .attr('data-divider-theme', 'd') + .attr('data-role', 'listview'); + + // Retrieve the list of the known DICOM modalities $.ajax({ url: '../modalities', type: 'GET', @@ -790,43 +797,66 @@ async: false, cache: false, success: function(modalities) { - var clickedModality = ''; - var items = $('<ul>') - .attr('data-divider-theme', 'd') - .attr('data-role', 'listview'); - - items.append('<li data-role="list-divider">DICOM modalities</li>'); + if (modalities.length > 0) + { + items.append('<li data-role="list-divider">DICOM modalities</li>'); - for (var i = 0; i < modalities.length; i++) { - var modality = modalities[i]; - var item = $('<li>') - .html('<a href="#" rel="close">' + modality + '</a>') - .attr('modality', modality) - .click(function() { - clickedModality = $(this).attr('modality'); - }); - items.append(item); + for (var i = 0; i < modalities.length; i++) { + var name = modalities[i]; + var item = $('<li>') + .html('<a href="#" rel="close">' + name + '</a>') + .attr('name', name) + .click(function() { + clickedModality = $(this).attr('name'); + }); + items.append(item); + } } - items.append('<li data-role="list-divider">Orthanc peers</li>'); - + // Retrieve the list of the known Orthanc peers + $.ajax({ + url: '../peers', + type: 'GET', + dataType: 'json', + async: false, + cache: false, + success: function(peers) { + if (peers.length > 0) + { + items.append('<li data-role="list-divider">Orthanc peers</li>'); - $('#dialog').simpledialog2({ - mode: 'blank', - animate: false, - headerText: 'Choose target', - headerClose: true, - width: '100%', - blankContent: items, - callbackClose: function() { - var timer; - function WaitForDialogToClose() { - if (!$('#dialog').is(':visible')) { - clearInterval(timer); - callback(clickedModality); + for (var i = 0; i < peers.length; i++) { + var name = peers[i]; + var item = $('<li>') + .html('<a href="#" rel="close">' + name + '</a>') + .attr('name', name) + .click(function() { + clickedPeer = $(this).attr('name'); + }); + items.append(item); } } - timer = setInterval(WaitForDialogToClose, 100); + + // Launch the dialog + $('#dialog').simpledialog2({ + mode: 'blank', + animate: false, + headerText: 'Choose target', + headerClose: true, + forceInput: false, + width: '100%', + blankContent: items, + callbackClose: function() { + var timer; + function WaitForDialogToClose() { + if (!$('#dialog').is(':visible')) { + clearInterval(timer); + callback(clickedModality, clickedPeer); + } + } + timer = setInterval(WaitForDialogToClose, 100); + } + }); } }); } @@ -835,16 +865,31 @@ $('#instance-store,#series-store,#study-store,#patient-store').live('click', function(e) { - ChooseDicomModality(function(modality) { - if (modality != '') { + ChooseDicomModality(function(modality, peer) { + var url; + var loading; + + if (modality != '') + { + url = '../modalities/' + modality + '/store'; + loading = '#dicom-store'; + } + + if (peer != '') + { + url = '../peers/' + peer + '/store'; + loading = '#peer-store'; + } + + if (url != '') { $.ajax({ - url: '../modalities/' + modality + '/store', + url: url, type: 'POST', dataType: 'text', data: $.mobile.pageData.uuid, async: true, // Necessary to block UI beforeSend: function() { - $.blockUI({ message: $('#loading') }); + $.blockUI({ message: $(loading) }); }, complete: function(s) { $.unblockUI(); @@ -852,10 +897,9 @@ success: function(s) { }, error: function() { - alert('Error during C-Store'); + alert('Error during store'); } - }); - + }); } }); });
--- a/OrthancServer/OrthancInitialization.cpp Tue Jul 16 12:51:27 2013 +0200 +++ b/OrthancServer/OrthancInitialization.cpp Tue Jul 16 13:48:33 2013 +0200 @@ -282,12 +282,30 @@ try { url = modalities[name].get(0u, "").asString(); - username = modalities[name].get(1u, "").asString(); - password = modalities[name].get(2u, "").asString(); + + if (modalities[name].size() == 1) + { + username = ""; + password = ""; + } + else if (modalities[name].size() == 3) + { + username = modalities[name].get(1u, "").asString(); + password = modalities[name].get(2u, "").asString(); + } + else + { + throw OrthancException(ErrorCode_BadFileFormat); + } } catch (...) { - throw OrthancException("Badly formatted Orthanc peer"); + throw OrthancException(ErrorCode_BadFileFormat); + } + + if (url.size() != 0 && url[url.size() - 1] != '/') + { + url += '/'; } }
--- a/OrthancServer/OrthancRestApi.cpp Tue Jul 16 12:51:27 2013 +0200 +++ b/OrthancServer/OrthancRestApi.cpp Tue Jul 16 13:48:33 2013 +0200 @@ -32,9 +32,10 @@ #include "OrthancRestApi.h" +#include "../Core/Compression/HierarchicalZipWriter.h" +#include "../Core/HttpClient.h" #include "../Core/HttpServer/FilesystemHttpSender.h" #include "../Core/Uuid.h" -#include "../Core/Compression/HierarchicalZipWriter.h" #include "DicomProtocol/DicomUserConnection.h" #include "FromDcmtkBridge.h" #include "OrthancInitialization.h" @@ -248,11 +249,12 @@ } - static void DicomStore(RestApi::PostCall& call) + static bool GetInstancesToExport(std::list<std::string>& instances, + const std::string& remote, + RestApi::PostCall& call) { RETRIEVE_CONTEXT(call); - std::string remote = call.GetUriComponent("id", ""); std::string stripped = Toolbox::StripSpaces(call.GetPostBody()); Json::Value request; @@ -264,13 +266,11 @@ else if (!call.ParseJsonRequest(request)) { // Bad JSON request - return; + return false; } - std::list<std::string> instances; if (request.isString()) { - LOG(INFO) << "Sending resource " << request.asString() << " to modality " << remote; context.GetIndex().LogExportedResource(request.asString(), remote); context.GetIndex().GetChildInstances(instances, request.asString()); } @@ -280,16 +280,15 @@ { if (!request[i].isString()) { - return; + return false; } std::string stripped = Toolbox::StripSpaces(request[i].asString()); if (!Toolbox::IsSHA1(stripped)) { - return; + return false; } - LOG(INFO) << "Sending resource " << stripped << " to modality " << remote; context.GetIndex().LogExportedResource(stripped, remote); std::list<std::string> tmp; @@ -301,6 +300,22 @@ else { // Neither a string, nor a list of strings. Bad request. + return false; + } + + return true; + } + + + static void DicomStore(RestApi::PostCall& call) + { + RETRIEVE_CONTEXT(call); + + std::string remote = call.GetUriComponent("id", ""); + + std::list<std::string> instances; + if (!GetInstancesToExport(instances, remote, call)) + { return; } @@ -310,6 +325,8 @@ for (std::list<std::string>::const_iterator it = instances.begin(); it != instances.end(); it++) { + LOG(INFO) << "Sending resource " << *it << " to modality \"" << remote << "\""; + std::string dicom; context.ReadFile(dicom, *it, FileContentType_Dicom); connection.Store(dicom); @@ -1649,6 +1666,51 @@ } } + static void PeerStore(RestApi::PostCall& call) + { + RETRIEVE_CONTEXT(call); + + std::string remote = call.GetUriComponent("id", ""); + + std::list<std::string> instances; + if (!GetInstancesToExport(instances, remote, call)) + { + return; + } + + std::string url, username, password; + GetOrthancPeer(remote, url, username, password); + + // Configure the HTTP client + HttpClient client; + if (username.size() != 0 && password.size() != 0) + { + client.SetCredentials(username.c_str(), password.c_str()); + } + + client.SetUrl(url + "instances"); + client.SetMethod(HttpMethod_Post); + + // Loop over the instances that are to be sent + for (std::list<std::string>::const_iterator + it = instances.begin(); it != instances.end(); it++) + { + LOG(INFO) << "Sending resource " << *it << " to peer \"" << remote << "\""; + + context.ReadFile(client.AccessPostData(), *it, FileContentType_Dicom); + + std::string answer; + if (!client.Apply(answer)) + { + LOG(ERROR) << "Unable to send resource " << *it << " to peer \"" << remote << "\""; + return; + } + } + + call.GetOutput().AnswerBuffer("{}", "application/json"); + } + + @@ -1737,6 +1799,7 @@ Register("/peers", ListPeers); Register("/peers/{id}", ListPeerOperations); + Register("/peers/{id}/store", PeerStore); Register("/instances/{id}/modify", ModifyInstance); Register("/series/{id}/modify", ModifySeriesInplace);
--- a/Resources/Configuration.json Tue Jul 16 12:51:27 2013 +0200 +++ b/Resources/Configuration.json Tue Jul 16 13:48:33 2013 +0200 @@ -107,6 +107,12 @@ // The list of the known Orthanc peers "OrthancPeers" : { - // "peer" : [ "http://localhost:8043/", "alice", "alicePassword" ] + /** + * Each line gives the base URL of an Orthanc peer, possibly + * followed by the username/password pair (if the password + * protection is enabled on the peer). + **/ + // "peer" : [ "http://localhost:8043/", "alice", "alicePassword" ] + // "peer2" : [ "http://localhost:8044/" ] } }