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.
452 lines
15 KiB
452 lines
15 KiB
|
3 weeks ago
|
|
||
|
|
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)
|
||
|
|
// })
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|