fix(core): 修复nwjs下server端文件下载异常
This commit is contained in:
@@ -254,6 +254,9 @@ Setting.configMenuGetValue = (obj) => {
|
|||||||
Setting.refreshUpdateMenuStatus = (localVersion, cloudVersion, needsUpdate, url) => {
|
Setting.refreshUpdateMenuStatus = (localVersion, cloudVersion, needsUpdate, url) => {
|
||||||
const $serverDiv = $('#setting-menu-update-server');
|
const $serverDiv = $('#setting-menu-update-server');
|
||||||
const $btnDiv = $('#setting-menu-update > div:nth-child(2)');
|
const $btnDiv = $('#setting-menu-update > div:nth-child(2)');
|
||||||
|
const $button = $btnDiv.children('button');
|
||||||
|
$button.removeClass('layui-btn-disabled');
|
||||||
|
$button.addClass('self-adaption-btn');
|
||||||
const $mixlyProgress = $serverDiv.find('.mixly-progress');
|
const $mixlyProgress = $serverDiv.find('.mixly-progress');
|
||||||
$serverDiv.find('span').css('display', 'none');
|
$serverDiv.find('span').css('display', 'none');
|
||||||
$mixlyProgress.hide();
|
$mixlyProgress.hide();
|
||||||
@@ -269,7 +272,9 @@ Setting.refreshUpdateMenuStatus = (localVersion, cloudVersion, needsUpdate, url)
|
|||||||
}
|
}
|
||||||
if (needsUpdate) {
|
if (needsUpdate) {
|
||||||
$btnDiv.css('display', 'flex');
|
$btnDiv.css('display', 'flex');
|
||||||
$btnDiv.children('button').off().one('click', (event) => {
|
$button.off().one('click', (event) => {
|
||||||
|
$button.addClass('layui-btn-disabled');
|
||||||
|
$button.removeClass('self-adaption-btn');
|
||||||
const eventSource = new EventSource(`/api/download?url=${encodeURIComponent(url)}&cloudVersion=${cloudVersion}`);
|
const eventSource = new EventSource(`/api/download?url=${encodeURIComponent(url)}&cloudVersion=${cloudVersion}`);
|
||||||
$mixlyProgress.show();
|
$mixlyProgress.show();
|
||||||
eventSource.onmessage = function(event) {
|
eventSource.onmessage = function(event) {
|
||||||
|
|||||||
@@ -172,72 +172,106 @@ router.get('/download', async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const { url, cloudVersion } = req.query;
|
const { url, cloudVersion } = req.query;
|
||||||
|
|
||||||
if(fs.existsSync(TEMP_FOLDER_PATH)) {
|
// 清理临时文件夹
|
||||||
|
if (fs.existsSync(TEMP_FOLDER_PATH)) {
|
||||||
deleteFolderRecursive(TEMP_FOLDER_PATH);
|
deleteFolderRecursive(TEMP_FOLDER_PATH);
|
||||||
}
|
}
|
||||||
fs.mkdirSync(TEMP_FOLDER_PATH);
|
fs.mkdirSync(TEMP_FOLDER_PATH, { recursive: true });
|
||||||
|
|
||||||
const filePath = path.resolve(TEMP_FOLDER_PATH, 'mixly.zip');
|
const filePath = path.resolve(TEMP_FOLDER_PATH, 'mixly.zip');
|
||||||
const fileStream = fs.createWriteStream(filePath);
|
const fileStream = fs.createWriteStream(filePath);
|
||||||
|
|
||||||
// 设置响应头
|
// 设置 SSE 响应头
|
||||||
res.setHeader('Content-Type', 'text/event-stream');
|
res.setHeader('Content-Type', 'text/event-stream');
|
||||||
res.setHeader('Transfer-Encoding', 'chunked');
|
res.setHeader('Cache-Control', 'no-cache');
|
||||||
|
res.setHeader('Connection', 'keep-alive');
|
||||||
|
res.flushHeaders();
|
||||||
|
|
||||||
// 发起下载请求
|
// 发起下载请求 - 添加 NW.js 特定配置
|
||||||
const response = await axios({
|
const response = await axios({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: url,
|
url: url,
|
||||||
responseType: 'stream'
|
responseType: 'stream',
|
||||||
|
timeout: 60000,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
||||||
|
},
|
||||||
|
adapter: require('axios/lib/adapters/http')
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalSize = parseInt(response.headers['content-length'], 10);
|
const totalSize = parseInt(response.headers['content-length'], 10) || 0;
|
||||||
|
|
||||||
let downloadedSize = 0;
|
let downloadedSize = 0;
|
||||||
let lastProgress = 0;
|
let lastProgress = 0;
|
||||||
|
|
||||||
// 发送进度信息
|
// 发送进度信息
|
||||||
const sendProgress = (progress) => {
|
const sendProgress = (progress) => {
|
||||||
if(progress !== lastProgress) {
|
if (progress !== lastProgress) {
|
||||||
res.write('data:' + JSON.stringify({ type: 'progress', progress }) + '\n\n');
|
const data = JSON.stringify({ type: 'progress', progress });
|
||||||
|
res.write(`data: ${data}\n\n`);
|
||||||
lastProgress = progress;
|
lastProgress = progress;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 发送解压信息
|
// 管道流处理
|
||||||
const sendUnzip = () => {
|
|
||||||
res.write('data:' + JSON.stringify({ type: 'unzip' }) + '\n\n');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 发送完成信息
|
|
||||||
const sendComplete = (version) => {
|
|
||||||
res.write('data:' + JSON.stringify({ type: 'complete', version }) + '\n\n');
|
|
||||||
res.end();
|
|
||||||
};
|
|
||||||
response.data.pipe(fileStream);
|
response.data.pipe(fileStream);
|
||||||
// 处理数据流
|
|
||||||
|
// 进度监控
|
||||||
response.data.on('data', (chunk) => {
|
response.data.on('data', (chunk) => {
|
||||||
downloadedSize += chunk.length;
|
downloadedSize += chunk.length;
|
||||||
const progress = Math.round((downloadedSize / totalSize) * 100);
|
if (totalSize > 0) {
|
||||||
sendProgress(progress);
|
const progress = Math.round((downloadedSize / totalSize) * 100);
|
||||||
|
sendProgress(progress);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 文件流完成
|
||||||
fileStream.on('finish', async () => {
|
fileStream.on('finish', async () => {
|
||||||
// 获取版本信息并保存
|
console.log('文件下载完成,开始解压');
|
||||||
saveVersionInfo(cloudVersion);
|
|
||||||
sendUnzip();
|
// 发送解压信息
|
||||||
|
res.write(`data: ${JSON.stringify({ type: 'unzip' })}\n\n`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const asyncZip = new AsyncAdmZip(filePath);
|
const asyncZip = new AsyncAdmZip(filePath);
|
||||||
await asyncZip.extractAllTo(path.resolve(__dirname, '../'));
|
await asyncZip.extractAllTo(path.resolve(__dirname, '../'));
|
||||||
sendComplete(cloudVersion);
|
|
||||||
if(fs.existsSync(TEMP_FOLDER_PATH)) {
|
// 保存版本信息
|
||||||
|
saveVersionInfo(cloudVersion);
|
||||||
|
|
||||||
|
// 发送完成信息
|
||||||
|
res.write(`data: ${JSON.stringify({ type: 'complete', version: cloudVersion })}\n\n`);
|
||||||
|
|
||||||
|
// 清理临时文件
|
||||||
|
if (fs.existsSync(TEMP_FOLDER_PATH)) {
|
||||||
deleteFolderRecursive(TEMP_FOLDER_PATH);
|
deleteFolderRecursive(TEMP_FOLDER_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.end();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error('解压失败:', error);
|
||||||
res.status(500).json({ error: '解压失败' });
|
res.write(`data: ${JSON.stringify({ type: 'error', message: '解压失败' })}\n\n`);
|
||||||
|
res.end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 错误处理
|
||||||
|
response.data.on('error', (error) => {
|
||||||
|
console.error('下载流错误:', error);
|
||||||
|
res.write(`data: ${JSON.stringify({ type: 'error', message: '下载流错误' })}\n\n`);
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
fileStream.on('error', (error) => {
|
||||||
|
console.error('文件流错误:', error);
|
||||||
|
res.write(`data: ${JSON.stringify({ type: 'error', message: '文件保存错误' })}\n\n`);
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.message);
|
console.error('下载过程错误:', error);
|
||||||
res.status(500).json({ error: '下载失败' });
|
res.write(`data: ${JSON.stringify({ type: 'error', message: '下载失败: ' + error.message })}\n\n`);
|
||||||
|
res.end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user