From f3d4ecb90309cf9d9a3f52158d7c1972cef89b00 Mon Sep 17 00:00:00 2001 From: "CHIN\\a5566" Date: Fri, 1 Mar 2024 16:56:46 +0800 Subject: [PATCH] feat: add export dicom dir 7z plugin - Use GET `/dicom-web/dicomdir?{attr=value}` to export dicom dir 7z file --- plugins/config.template.js | 10 ++++ plugins/dicomdir/getDicomDirService.js | 64 ++++++++++++++++++++++++++ plugins/dicomdir/index.js | 18 ++++++++ 3 files changed, 92 insertions(+) create mode 100644 plugins/dicomdir/getDicomDirService.js create mode 100644 plugins/dicomdir/index.js diff --git a/plugins/config.template.js b/plugins/config.template.js index ecd56b1a..4ad9bbad 100644 --- a/plugins/config.template.js +++ b/plugins/config.template.js @@ -27,5 +27,15 @@ module.exports.pluginsConfig = { baseUrl: "http://127.0.0.1/fhir" } } + }, + "dicomdir": { + enable: false, + before: true, + routers: [ + { + path: "/dicom-web/dicomdir", + method: "get" + } + ] } }; \ No newline at end of file diff --git a/plugins/dicomdir/getDicomDirService.js b/plugins/dicomdir/getDicomDirService.js new file mode 100644 index 00000000..888bdd66 --- /dev/null +++ b/plugins/dicomdir/getDicomDirService.js @@ -0,0 +1,64 @@ +const { DicomWebServiceError, DicomWebStatusCodes } = require("@error/dicom-web-service"); +const { DicomDir } = require("@models/DICOM/dcm4che/dicomdir"); +const { InstanceModel } = require("@models/mongodb/models/instance.model"); +const { BaseQueryService } = require("@root/api/dicom-web/service/base-query.service"); +const { raccoonConfig } = require("@root/config-class"); +const { SevenZip } = require("@root/utils/sevenZip"); +const path = require("path"); +const shortHash = require("shorthash2"); +const { v4: uuidV4 } = require("uuid"); + +class GetDicomDirService extends BaseQueryService { + constructor(req, res) { + super(req, res); + } + + async getDicomDirSevenZip() { + let instanceFiles = await this.#getInstanceFiles(); + + if (instanceFiles.length === 0) throw new DicomWebServiceError(DicomWebStatusCodes.ProcessingFailure, "No any instance found", 404); + + let dicomDirFilename = path.join(raccoonConfig.dicomWebConfig.storeRootPath, "DICOMDIR" + shortHash(uuidV4())); + + let relativePaths = [ + path.relative(raccoonConfig.dicomWebConfig.storeRootPath, dicomDirFilename) + ]; + for(let file of instanceFiles) { + let relativePath = path.relative(raccoonConfig.dicomWebConfig.storeRootPath, file.instancePath); + relativePaths.push(relativePath); + } + + let dicomDirInstance = new DicomDir(dicomDirFilename, ...instanceFiles.map(v=> v.instancePath)); + await dicomDirInstance.exec(); + + await this.compressTo7zip(`${dicomDirFilename}.7z`, relativePaths); + return `${dicomDirFilename}.7z`; + } + + async #getInstanceFiles() { + return await InstanceModel.getInstancePathsByQueryOpts({ + query: this.query, + requestParams: this.request.params + }); + } + + /** + * + * @param {string} zipFile + * @param {string[]} relativePaths + */ + async compressTo7zip(zipFile, relativePaths) { + let sevenZip = new SevenZip("7z", undefined, zipFile); + + for(let i = 0 ; i < relativePaths.length ; i++) { + sevenZip.addCmd(relativePaths[i]); + } + + let cwd = path.normalize(raccoonConfig.dicomWebConfig.storeRootPath); + await sevenZip.pack({ + cwd: cwd + }); + } +} + +module.exports.GetDicomDirService = GetDicomDirService; \ No newline at end of file diff --git a/plugins/dicomdir/index.js b/plugins/dicomdir/index.js new file mode 100644 index 00000000..44deb62c --- /dev/null +++ b/plugins/dicomdir/index.js @@ -0,0 +1,18 @@ +const { app } = require("@root/app"); +const fs = require("fs"); +const path = require("path"); +const { GetDicomDirService } = require("./getDicomDirService"); + +let pluginConfigFile = path.join(__dirname, "../config.template.js"); +if (fs.existsSync(path.join(__dirname, "../config.js"))) pluginConfigFile = path.join(__dirname, "../config.js"); + +const { pluginsConfig } = require(pluginConfigFile); + +app.get("/dicom-web/dicomdir", async (req, res) => { + let getDicomDirService = new GetDicomDirService(req, res); + + let dicomDirSevenZipFilename = await getDicomDirService.getDicomDirSevenZip(); + return fs.createReadStream(dicomDirSevenZipFilename).pipe(res); +}); + +module.exports = []; \ No newline at end of file