cvpilot-tool/apps/desktop/electron/ipcEvent/dicom/util.ts
2024-09-20 12:30:56 +08:00

112 lines
3.0 KiB
TypeScript

import path from "node:path";
import fs from "node:fs";
import { uploadDicomFile } from "../../core/pacs";
/**
* 检查文件是否为 DICOM 文件(通过 Magic Number 判断)
* @param filePath 文件路径
* @returns 是否为 DICOM 文件
*/
const isDICOMFile = async (filePath: string) => {
try {
// 打开文件以进行读取
const fileHandle = await fs.promises.open(filePath, "r");
const buffer = Buffer.alloc(132); // 创建一个 132 字节的缓冲区
// 从文件中读取前 132 个字节
await fileHandle.read(buffer, 0, 132, 0);
await fileHandle.close(); // 关闭文件
// 检查 "DICM" 标识 (偏移 128-131 字节)
const magicNumber = buffer.toString("utf-8", 128, 132);
return magicNumber === "DICM";
} catch (error) {
console.error(`Error reading file ${filePath}:`, error);
return false;
}
};
/**
* 定义一个异步函数来递归地查找.dcm文件
* @param dir
* @param fileList
* @returns
*/
export const filterDicoms = async (
dir: string,
fileList: string[] = []
): Promise<string[]> => {
const files = await fs.promises.readdir(dir, { withFileTypes: true });
await Promise.all(
files.map(async (file) => {
const filePath = path.join(dir, file.name);
if (file.isDirectory()) {
await filterDicoms(filePath, fileList); // 递归调用以遍历子目录
} else if (await isDICOMFile(filePath)) {
fileList.push(filePath);
}
})
);
return fileList;
};
interface UploadFilesInBatchesParams {
filePaths: string[];
batchSize: number;
orthancUrl?: string;
feedback?: (detail: {
progress: number;
totalSuccess: number;
totalFailed: number;
}) => void;
}
/**
* 批量上传文件,并提供进度更新。
* @param filePaths 文件路径数组。
* @param batchSize 每批上传的文件数量。
* @param orthancUrl Orthanc 服务器的 URL。
* @param feedback 每批处理完成后调用的回调函数。
*/
export const uploadFilesInBatches = async ({
filePaths,
batchSize,
feedback,
}: UploadFilesInBatchesParams) => {
const totalStartTime = Date.now();
let totalSuccess = 0;
let totalFailed = 0;
const totalFiles = filePaths.length;
for (let i = 0; i < totalFiles; i += batchSize) {
const batch = filePaths.slice(i, i + batchSize);
const batchResults = await Promise.allSettled(
batch.map((filePath) => uploadDicomFile(filePath))
);
batchResults.forEach((result) => {
if (result.status === "fulfilled" && result.value) {
totalSuccess++;
} else {
totalFailed++;
}
});
const actualProcessed = i + batch.length;
const progress = Math.round((actualProcessed / totalFiles) * 100);
const detail = {
progress: Math.min(progress, 100),
totalSuccess,
totalFailed,
};
if (feedback) feedback(detail);
}
const totalEndTime = Date.now();
console.log(
`[上传序列] Success: ${totalSuccess}, Failed: ${totalFailed}, Total upload time: ${
totalEndTime - totalStartTime
} ms`
);
};