diff --git a/examples/simple_server/src/main.rs b/examples/simple_server/src/main.rs index ef3da06..b1c8fd5 100644 --- a/examples/simple_server/src/main.rs +++ b/examples/simple_server/src/main.rs @@ -235,6 +235,57 @@ fn search_instances( Ok(instances) } +fn retrieve_study( + study_uid: &str, +) -> Result>, Box> { + let files = get_all_data_files(); + let dcm_files = files + .iter() + .filter(|file| { + let dcm = FileDicomObject::open_file(file).unwrap().into_inner(); + dcm.element(tags::STUDY_INSTANCE_UID) + .unwrap() + .to_str() + .unwrap() + == study_uid + }) + .map(|file| FileDicomObject::open_file(file)) + .collect::, _>>()?; + + Ok(dcm_files) +} + +fn retrieve_series( + study_uid: &str, + series_uid: &str, +) -> Result>, Box> { + let files = get_all_data_files(); + let dcm_files = files + .iter() + .filter(|file| { + let dcm = FileDicomObject::open_file(file).unwrap().into_inner(); + if dcm + .element(tags::STUDY_INSTANCE_UID) + .unwrap() + .to_str() + .unwrap() + != study_uid + { + return false; + } + + dcm.element(tags::SERIES_INSTANCE_UID) + .unwrap() + .to_str() + .unwrap() + == series_uid + }) + .map(|file| FileDicomObject::open_file(file)) + .collect::, _>>()?; + + Ok(dcm_files) +} + fn retrieve_instance( study_uid: &str, series_uid: &str, @@ -307,6 +358,8 @@ async fn main() -> std::io::Result<()> { search_instances: search_instances, search_series: search_series, search_study: search_study, + retrieve_study: retrieve_study, + retrieve_series: retrieve_series, retrieve_instance: retrieve_instance, store_instances: store_instances, })) diff --git a/server/src/filter.rs b/server/src/filter.rs index 3d63b46..b444263 100644 --- a/server/src/filter.rs +++ b/server/src/filter.rs @@ -1,8 +1,8 @@ -use dicom::dictionary_std::tags; + use dicom_object::InMemDicomObject; use crate::QidoStudyQuery; -pub fn study_filter(dcm: &InMemDicomObject, query: &QidoStudyQuery) -> bool { +pub fn study_filter(_dcm: &InMemDicomObject, _query: &QidoStudyQuery) -> bool { true } diff --git a/server/src/lib.rs b/server/src/lib.rs index ee0a0cf..ee904af 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -30,6 +30,15 @@ pub struct DicomWebServer { Option<&str>, // series_instance_uid &QidoInstanceQuery, ) -> Result, Box>, + pub retrieve_study: + fn( + &str, // study_instance_uid + ) -> Result>, Box>, + pub retrieve_series: + fn( + &str, // study_instance_uid + &str, // series_instance_uid + ) -> Result>, Box>, pub retrieve_instance: fn( &str, // study_instance_uid diff --git a/server/src/multipart/builder.rs b/server/src/multipart/builder.rs index f89e226..bd9e414 100644 --- a/server/src/multipart/builder.rs +++ b/server/src/multipart/builder.rs @@ -1,4 +1,4 @@ -use actix_web::http::header::HeaderMap; + use std::io::{self, Read, Write}; use uuid::Uuid; diff --git a/server/src/wado.rs b/server/src/wado.rs index 127277c..1895452 100644 --- a/server/src/wado.rs +++ b/server/src/wado.rs @@ -1,6 +1,5 @@ use std::{ - fs, - io::{Cursor, Write}, + io::{Write}, }; use actix_web::{get, web, HttpResponse, Responder}; @@ -11,16 +10,72 @@ use crate::{multipart::MultipartWriter, DicomWebServer}; /// /// #[get("/studies/{study_uid}")] -pub async fn retrieve_study(_study_uid: web::Path) -> impl Responder { - HttpResponse::Ok().body("retrieve_study") +pub async fn retrieve_study( + callbacks: web::Data, + study_uid: web::Path, +) -> impl Responder { + let result = (callbacks.retrieve_study)(&study_uid); + + match result { + Ok(dcm_files) => { + let mut mp = MultipartWriter::new(); + for dcm_file in dcm_files { + let mut data: Vec = Vec::new(); + + // Write the DICOM file to memory and add it to our stream + if let Err(e) = dcm_file.write_all(&mut data) { + return HttpResponse::InternalServerError().body(e.to_string()); + } + + if let Err(e) = mp.add(&*data, "Content-Type: application/dicom") { + return HttpResponse::InternalServerError().body(e.to_string()); + } + } + + let content_type = format!( + "multipart/related; type=application/dicom; boundary={}", + mp.boundary + ); + + return HttpResponse::Ok().content_type(content_type).body(mp.data); + } + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + } } #[get("/studies/{study_uid}/series/{series_uid}")] pub async fn retrieve_series( - _study_uid: web::Path, - _series_uid: web::Path, + callbacks: web::Data, + path: web::Path<(String, String)>, ) -> impl Responder { - HttpResponse::Ok().body("retrieve_series") + let (study_uid, series_uid) = path.into_inner(); + let result = (callbacks.retrieve_series)(&study_uid, &series_uid); + + match result { + Ok(dcm_files) => { + let mut mp = MultipartWriter::new(); + for dcm_file in dcm_files { + let mut data: Vec = Vec::new(); + + // Write the DICOM file to memory and add it to our stream + if let Err(e) = dcm_file.write_all(&mut data) { + return HttpResponse::InternalServerError().body(e.to_string()); + } + + if let Err(e) = mp.add(&*data, "Content-Type: application/dicom") { + return HttpResponse::InternalServerError().body(e.to_string()); + } + } + + let content_type = format!( + "multipart/related; type=application/dicom; boundary={}", + mp.boundary + ); + + return HttpResponse::Ok().content_type(content_type).body(mp.data); + } + Err(e) => return HttpResponse::InternalServerError().body(e.to_string()), + } } #[get("/studies/{study_uid}/series/{series_uid}/instances/{instance_uid}")] @@ -44,16 +99,6 @@ pub async fn retrieve_instance( if let Err(e) = mp.add(&*data, "Content-Type: application/dicom") { return HttpResponse::InternalServerError().body(e.to_string()); } - { - let mut file = fs::OpenOptions::new() - .create(true) // To create a new file - .write(true) - // either use the ? operator or unwrap since it returns a Result - .open("test.txt") - .unwrap(); - - file.write_all(&mp.data); - } let content_type = format!( "multipart/related; type=application/dicom; boundary={}",