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 => { 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).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; };