You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

451 lines
15 KiB

import fs from 'fs';// npm i fs-extra
import path from 'path';
import axios from 'axios';// 确保 axios 已安装
import FormData from 'form-data';// 确保 form-data 已安装
const { BrowserWindow, dialog } = require('electron');
const Store = require("electron-store");
const store = new Store();
const os = require('os');
function getIPAddress() {
const networkInterfaces = os.networkInterfaces();
for (const name of Object.keys(networkInterfaces)) {
for (const net of networkInterfaces[name]) {
// IPv4且未被内部使用
if (net.family === 'IPv4' && !net.internal) {
return net.address;
}
}
}
return null; // 如果没有找到合适的IP地址
}
const userDataPath = process.cwd();
const configPath = path.join(userDataPath, 'config.json');
let latestMTime = 0
let checkTimeout = null
function showMessage(message, title = '提示') {
dialog.showMessageBox({
type: 'info', // 可以是 'none', 'info', 'error', 'question' 或 'warning'
title: title,
message: message,
buttons: [] // 自定义按钮文本
}).then(result => {
console.log(result.response); // '0' 表示第一个按钮,以此类推
}).catch(err => {
console.log(err);
});
}
// 读取配置文件
function loadConfig() {
try {
const data = fs.readFileSync(configPath, 'utf8');
return JSON.parse(data);
} catch (error) {
console.error('Error loading config:', error);
return {}; // 或者返回一个默认配置对象
}
}
// 日志文件路径
const cwd = process.cwd(); //获取项目的根目录
const logFilePath = path.join(cwd, 'api.log');
// 函数:写入日志
function logApiCall(data) {
const logEntry = `[${new Date().toLocaleString()}] ${data}\n`;
fs.appendFile(logFilePath, logEntry, (err) => {
if (err) {
console.error('写入日志时出错:', err);
}
});
}
export const uploadLatestFile = async (id) => {
// const cwd = process.cwd(); //获取项目的根目录
// 获取文件夹下所有文件
let dataJson = loadConfig()
let directoryPath = path.join(`${dataJson.device.filePathDisc}:`, dataJson.device.file_path);
let fileExt = null
let oldPath = null
let newPath = null
// const directoryPath = path.join(`C:`, '检测记录');
const files = fs.readdirSync(directoryPath);
// 3. 获取文件元数据并记录修改时间
const filesWithStats = files
.map(fileName => {
const filePath = path.join(directoryPath, fileName);
return {
name: fileName,
stats: fs.statSync(filePath)
};
})
.filter(item => item.stats.isFile() || item.stats.isDirectory()); // 可选:过滤有效项
if (filesWithStats.length === 0) {
logApiCall("上传目录为空,无文件可上传");
store.set('key', 'error');
return;
}
const latestFile = filesWithStats.reduce((prev, current) => {
// 使用 mtimeMs(毫秒时间戳)确保精度
return current.stats.mtimeMs > prev.stats.mtimeMs ? current : prev;
});
// 获取最新文件
// const latestFile = files.sort((a, b) => b.mtime - a.mtime)[0];
const stats = fs.statSync(path.join(directoryPath, latestFile.name));
if (stats.isFile()) {//文件处理
fileExt = path.extname(latestFile.name); // 正确获取扩展名(包含点)
oldPath = latestFile.name;
// newPath = `${latestFile.name}`;//不修改文件名
newPath = `${id}${fileExt}`;//修改文件名
} else if (stats.isDirectory()) {//文件夹处理
directoryPath = path.join(`${dataJson.device.filePathDisc}:`, `${dataJson.device.file_path}/${latestFile.name}`);
const filess = fs.readdirSync(directoryPath);
const filesWithStatss = filess.map(fileName => {
const filePath = path.join(directoryPath, fileName);
return {
name: fileName,
stats: fs.statSync(filePath) // 获取文件状态
};
});
const latestFiles = filesWithStatss.reduce((prev, current) => {
// 使用 mtimeMs(毫秒时间戳)确保精度
return current.stats.mtimeMs > prev.stats.mtimeMs ? current : prev;
});
let fileExts = path.extname(latestFiles.name); // 正确获取扩展名(包含点)
oldPath = latestFiles.name;
// newPath = `${latestFiles.name}`; 不修改文件名
newPath = `${id}${fileExts}`; //修改文件名
}
logApiCall(`重命名之前的文件: ${path.join(directoryPath, oldPath)},${path.join(directoryPath, newPath)}`);
fs.renameSync(path.join(directoryPath, oldPath), path.join(directoryPath, newPath))
//
logApiCall(`获取文件信息: ${JSON.stringify(fs.createReadStream(path.join(directoryPath, newPath)))}`);
try {
// // 采用form-data 的方式上传
const formData = new FormData();
formData.append(
'file',
fs.readFileSync(path.join(directoryPath, newPath)),
);
formData.append('deviceId', dataJson.device.code);
formData.append('orderNumber', id);
formData.append('deviceModel', dataJson.device.codeType);
logApiCall(`上传路径: ${path.join(directoryPath, newPath)}`);
logApiCall(`上传接口: ${dataJson.device.address}/upper/parsing`);
logApiCall(`上传参数: ${JSON.stringify(formData)}`);
// 上传文件
const result = await axios.post(
'http://49.232.74.228:80/blade-resource/oss/endpoint/put-file-attach',
formData,
{
headers: {
...formData.getHeaders(),
},
},
)
logApiCall(`上传返回: ${JSON.stringify(result)}`);
if (result.data.msg == '操作成功') {
store.set('key', 'success');
store.set('resultDate', JSON.stringify(result.data));
} else {
logApiCall(`上传失败1: ${JSON.stringify(result)}`);
store.set('key', 'error');
}
} catch (error) {
store.set('key', 'error');
const errorMsg = error.response
? JSON.stringify(error.response.data)
: error.message || 'Unknown error';
logApiCall(`请求失败2: ${errorMsg}`);
}
};
// 记录已上传的文件,避免重复上传(模块级变量,所有调用共享)
let uploadedFiles = new Set();
// 防止多次调用导致多个循环
let isWatching = false;
// 监控文件夹上传
export const watchUploadLatestFile = async (id) => {
// 如果已经在监控,直接返回
if (isWatching) {
logApiCall("监控已在运行,跳过重复调用");
return;
}
isWatching = true;
store.set("key", "error");
let dataJson = loadConfig();
let directoryPath = path.join(
`${dataJson.device.filePathDisc}:`,
dataJson.device.file_path,
);
// 获取文件夹中最新文件的函数
const getLatestFile = () => {
try {
const files = fs.readdirSync(directoryPath);
if (files.length === 0) {
return null; // 文件夹为空
}
// 获取所有文件的状态并找到最新的
const filesWithStats = files
.map((fileName) => {
const filePath = path.join(directoryPath, fileName);
try {
const stats = fs.statSync(filePath);
return {
name: fileName,
path: filePath,
mtimeMs: stats.mtimeMs,
size: stats.size,
};
} catch (error) {
console.error(`无法获取文件状态: ${fileName}`, error);
return null;
}
})
.filter(Boolean); // 过滤掉无法获取状态的文件
if (filesWithStats.length === 0) {
return null; // 没有有效文件
}
// 找到修改时间最新的文件
const latestFile = filesWithStats.reduce((prev, current) => {
return current.mtimeMs > prev.mtimeMs ? current : prev;
});
return latestFile;
} catch (error) {
console.error("读取文件夹失败:", error);
return null;
}
};
// 获取初始文件列表
let previousFiles = new Set(fs.readdirSync(directoryPath));
// 延迟函数
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// 使用 while 循环替代 setInterval
while (true) {
try {
const currentFiles = new Set(fs.readdirSync(directoryPath));
const currentLatestFile = getLatestFile();
logApiCall(`循环读取新文件: ${Array.from(currentFiles)}`);
logApiCall(`之前状态文件: ${Array.from(previousFiles)}`);
// 检查是否有新增文件
const newFiles = Array.from(currentFiles).filter(
(file) => !previousFiles.has(file),
);
logApiCall(`新增文件: ${newFiles}`);
if (newFiles.length > 0 && currentLatestFile) {
logApiCall(`发现新增文件: ${newFiles.join(", ")}`);
// 只上传最新文件,且确保该文件未被上传过
if (!uploadedFiles.has(currentLatestFile.name)) {
logApiCall(
`标记已上传的文件列表: ${JSON.stringify(Array.from(uploadedFiles))}`,
);
// 标记为已上传
uploadedFiles.add(currentLatestFile.name);
logApiCall(
`添加后的文件列表: ${JSON.stringify(Array.from(uploadedFiles))}`,
);
// 上传最新的文件
await watchUpload(currentLatestFile, id);
} else {
logApiCall(`文件 ${currentLatestFile.name} 已经上传过,跳过`);
}
} else if (!currentLatestFile) {
logApiCall("文件夹中没有文件");
} else {
logApiCall("没有新增文件");
}
// 更新文件列表
previousFiles = currentFiles;
} catch (error) {
logApiCall(`检查文件夹时出错: ${error.message}`);
}
// 等待指定时间后再进行下一次检查
await sleep(dataJson.device.reconnect_time * 2000);
}
};
// 上传最新文件的函数
async function watchUpload(latestFile, id) {
const filePath = latestFile.path;
let dataJson = loadConfig();
try {
logApiCall(`开始上传最新文件: ${filePath}`);
// 采用form-data的方式上传
const formData = new FormData();
formData.append("file", fs.createReadStream(filePath));
formData.append("deviceId", dataJson.device.code);
formData.append("orderNumber", id);
formData.append("deviceModel", dataJson.device.codeType);
// logApiCall(`上传formData: ${JSON.stringify(formData)}`);
logApiCall(`上传路径: ${filePath}`);
logApiCall(`上传接口: ${dataJson.device.address}/upper/send`);
// 上传文件
const result = await axios.post(
dataJson.device.address + "/upper/send",
formData,
{
headers: {
...formData.getHeaders(),
},
},
);
logApiCall(`上传返回: ${JSON.stringify(result.data)}`);
if (result.data.msg == "操作成功") {
// showMessage(`文件 ${latestFile.name} 上传成功`);
store.set("key", "success");
} else {
store.set("key", "success");
// showMessage(`文件 ${latestFile.name} 上传失败: ${result.data.msg}`);
}
} catch (error) {
store.set("key", "success");
// showMessage(`文件 ${latestFile.name} 上传失败: ${JSON.stringify(error)}`);
logApiCall(`请求失败: ${JSON.stringify(error)}`);
}
}
// 停止监听的函数
export const stopFileWatching = () => {
if (checkTimeout) {
clearInterval(checkTimeout);
console.log('文件夹监听已停止');
}
}
// 监控文件上传并获取解析之后的数据
export const watchUploadLatestAnalysisFile = async (id) => {
store.set('key', '');
let newPath = null
let fileExt = null
let dataJson = loadConfig()
let directoryPath = path.join(`${dataJson.device.filePathDisc}:`, dataJson.device.file_path);
const files = fs.readdirSync(directoryPath)
// 遍历所有文件获取最新修改时间
const filesWithStats = files.map(fileName => {
const filePath = path.join(directoryPath, fileName);
return {
name: fileName,
stats: fs.statSync(filePath) // 获取文件状态
};
});
const latestFile = filesWithStats.reduce((prev, current) => {
// 使用 mtimeMs(毫秒时间戳)确保精度
return current.stats.mtimeMs > prev.stats.mtimeMs ? current : prev;
});
// 获取最新文件
const stats = fs.statSync(path.join(directoryPath, latestFile.name));
let newLatestMTime = stats.mtimeMs
latestMTime = stats.mtimeMs //获取最新的以此上传文件的时间
fileExt = path.extname(latestFile.name); // 正确获取扩展名(包含点)
newPath = `${latestFile.name}`;
checkTimeout = setInterval(async () => {
logApiCall(`上传文件解析修改日期开始:${newLatestMTime} 上传文件解析最新修改:${latestMTime}`);
if (newLatestMTime == latestMTime) {
// 遍历所有文件获取最新修改时间
let newStats = fs.statSync(path.join(directoryPath, latestFile.name));
newLatestMTime = newStats.mtimeMs
logApiCall(`上传文件解析未被修改过: ${path.join(directoryPath, newPath)}`);
console.log('上传文件解析未被修改过', directoryPath)
} else {
clearTimeout(checkTimeout)
logApiCall(`上传文件解析被修改过: ${path.join(directoryPath, newPath)}`);
console.log('上传文件解析被修改过', directoryPath)
// 采用form-data 的方式上传
const formData = new FormData();
formData.append(
'file',
fs.createReadStream(path.join(directoryPath, newPath)),
);
formData.append('deviceId', dataJson.device.code);
formData.append('orderNumber', id);
formData.append('deviceModel', dataJson.device.codeType);
logApiCall(`上传文件解析路径: ${path.join(directoryPath, newPath)}`);
logApiCall(`上传文件解析内容: ${JSON.stringify(formData)}`);
logApiCall(`上传文件解析接口: ${dataJson.device.address}/upper/parsing`);
// 上传文件
try {
const result = await axios.post(
dataJson.device.address + '/upper/parsing',
formData,
{
headers: {
...formData.getHeaders(),
},
},
)
logApiCall(`上传返回: ${JSON.stringify(result.data)}`);
if (result.data.msg == '操作成功') {
// showMessage('上传成功');
store.set('key', 'success');
store.set('resultDate', JSON.stringify(result.data));
// resolve(`文件上传成功`);
} else {
// reject(new Error(`上传失败${result.data.msg}`));
// store.set('key', 'error');
store.set('key', 'error');
// showMessage(`上传失败${result.data.msg}`);
}
} catch (error) {
// store.set('key', 'error');
store.set('key', 'error');
// showMessage(`上传失败${JSON.stringify(error)}`);
logApiCall(`请求失败: ${JSON.stringify(error)}`);
}
}
}, dataJson.device.reconnect_time * 1000)
// })
}