UNPKG

cod-dicomweb-server

Version:

A wadors server proxy that get data from a Cloud Optimized Dicom format.

150 lines (149 loc) 5.92 kB
import { get } from 'idb-keyval'; import { FILE_SYSTEM_ROUTES, IDB_DIR_HANDLE_KEY } from './constants/dataRetrieval'; let directoryHandle; export async function getDirectoryHandle() { try { if (!directoryHandle) { directoryHandle = (await get(IDB_DIR_HANDLE_KEY)); } if (!directoryHandle) { directoryHandle = await navigator.storage.getDirectory(); } return directoryHandle; } catch (error) { console.warn(`Error getting directoryhandle: ${error.message}`); } } async function readJsonFile(directoryHandle, name) { return await directoryHandle .getFileHandle(name) .then((fileHandle) => fileHandle .getFile() .then((file) => file.text()) .then((metadataString) => JSON.parse(metadataString))) .catch(() => null); } async function readArrayBufferFile(directoryHandle, name) { return await directoryHandle .getFileHandle(name) .then((fileHandle) => fileHandle.getFile().then((file) => file.arrayBuffer())) .catch(() => null); } export async function readFile(directoryHandle, name, options = {}) { if (!name) { return; } const pathParts = name.split('/'); let currentDir = directoryHandle; try { for (let i = 0; i < pathParts.length - 1; i++) { currentDir = await currentDir.getDirectoryHandle(pathParts[i], { create: true }); } const fileName = pathParts.at(-1); if (options.isJson) { return readJsonFile(currentDir, fileName); } else { return readArrayBufferFile(currentDir, fileName).catch(async () => { console.warn(`Error reading the file ${name} from partial folder, trying from full file`); if (options.offsets && pathParts.includes(FILE_SYSTEM_ROUTES.Partial)) { try { pathParts.splice(pathParts.findIndex((part) => part === FILE_SYSTEM_ROUTES.Partial), 1); currentDir = directoryHandle; for (let i = 0; i < pathParts.length - 1; i++) { currentDir = await currentDir.getDirectoryHandle(pathParts[i], { create: true }); } const convertedFileName = pathParts.at(-1).split('_')[0] + '.tar'; const fileArraybuffer = await readArrayBufferFile(currentDir, convertedFileName); return fileArraybuffer.slice(options.offsets.startByte, options.offsets.endByte); } catch (error) { console.warn(`Error reading the file ${name}: ${error.message}`); } } }); } } catch (error) { console.warn(`Error reading the file ${name}: ${error.message}`); } } export async function writeFile(directoryHandle, name, file, isJson = false) { try { const pathParts = name.split('/'); let currentDir = directoryHandle; for (let i = 0; i < pathParts.length - 1; i++) { currentDir = await currentDir.getDirectoryHandle(pathParts[i], { create: true }); } const fileName = pathParts.at(-1); const fileHandle = await currentDir.getFileHandle(fileName, { create: true }); // @ts-ignore const fileWritable = await fileHandle.createWritable(); if (isJson) { await fileWritable.write(JSON.stringify(file)); } else { await fileWritable.write(file); } await fileWritable.close(); } catch (error) { console.warn(`Error writing the file ${name}: ${error.message}`); } } export function download(fileName, file) { try { const blob = new Blob([file], { type: 'application/x-tar' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = fileName; a.click(); URL.revokeObjectURL(url); return true; } catch (error) { console.warn(`Error downloading file - ${fileName}: ` + error.message); return false; } } export async function clearPartialFiles() { const removePartialFolder = async (dirHandle) => { // @ts-ignore for await (const [name, handle] of dirHandle.entries()) { if (handle.kind === 'directory') { if (name.toLowerCase() === FILE_SYSTEM_ROUTES.Partial) { await dirHandle.removeEntry(name, { recursive: true }).catch((e) => console.warn(`Failed to remove ${name}:`, e)); } else { // Recurse into other directories await removePartialFolder(handle); } } } }; try { await removePartialFolder(directoryHandle); } catch (error) { console.warn(`Error clearing partial files: ${error.message}`); } } export function parseCachePath(url) { const urlObj = new URL(url); const bucketPath = urlObj.pathname.match(/\/(.*?)\/studies/)[1]; const [studyInstanceUID, _, seriesInstanceUID] = urlObj.pathname.match(/studies\/(.*?)(\.tar|\/metadata.json)/)[1].split('/'); return `${bucketPath}/${studyInstanceUID}/${seriesInstanceUID}`; } export function createStreamingFileName(url) { return `${parseCachePath(url)}/${url.split('series/')[1]}`; } export function createPartialFileName(url, offsets) { const seriesInstanceUID = url.match(/series\/(.*?).tar/)[1]; const offsetPart = `${offsets ? `_${offsets?.startByte}_${offsets?.endByte}` : ''}`; return `${parseCachePath(url)}/${FILE_SYSTEM_ROUTES.Partial}/${seriesInstanceUID}${offsetPart}.dcm`; } export function createMetadataFileName(url) { return `${parseCachePath(url)}/metadata.json`; }