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
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) |
|
// }) |
|
|
|
|
|
} |
|
|
|
|