cvpilot-tool/apps/desktop/electron/ipcEvent/dicom/util.ts

101 lines
3.1 KiB
TypeScript

import path from "node:path";
import fs from "node:fs";
import axios from "axios";
import FormData from "form-data";
import log from "electron-log";
/**
* 检查文件是否为 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;
};
export const uploadDicomFile = async (
filePath: string,
orthancUrl: string = "http://localhost:8042"
) => {
try {
const buffer = await fs.promises.readFile(filePath);
const fd = new FormData();
fd.append("files", buffer);
const url = `${orthancUrl}/instances`;
const headers = { "Content-Type": "multipart/form-data" };
const { status } = await axios.post(url, fd, { headers });
return status === 200;
} catch (error) {
log.error("Failed to upload DICOM file:", error);
console.error("Failed to upload DICOM file:", error);
}
};
export const uploadFilesInBatches = async (
filePaths: string[],
batchSize: number,
orthancUrl: string = "http://localhost:8042"
) => {
const results = [];
const totalStartTime = Date.now(); // 记录总体开始时间
for (let i = 0; i < filePaths.length; i += batchSize) {
const batch = filePaths.slice(i, i + batchSize);
const batchResults = await Promise.allSettled(
batch.map((filePath) => uploadDicomFile(filePath, orthancUrl))
);
// 提取状态为 'fulfilled' 的结果的 value
const fulfilledResults = batchResults
.filter((result) => result.status === "fulfilled")
.map((result) => (result as PromiseFulfilledResult<boolean>).value);
results.push(...fulfilledResults);
}
const totalEndTime = Date.now(); // 记录总体结束时间
const totalSuccess = results.filter(Boolean).length;
const totalFailed = results.length - totalSuccess;
log.info(
`[上传序列] Success: ${totalSuccess}, Failed: ${totalFailed}, Total upload time: ${
totalEndTime - totalStartTime
} ms`
);
return results;
};