Files
huishou/upload-files.js
T
2026-07-27 14:07:26 +08:00

95 lines
3.6 KiB
JavaScript

const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');
const conn = new Client();
const localH5Dir = path.join(__dirname, 'dist', 'build', 'h5');
const remoteH5Dir = '/www/huishou/dist/build/h5';
function uploadFile(sftp, localPath, remotePath, callback) {
fs.readFile(localPath, (err, content) => {
if (err) { callback(err); return; }
sftp.mkdir(path.dirname(remotePath), { recursive: true }, (mkdirErr) => {
if (mkdirErr && mkdirErr.code !== 4) { callback(mkdirErr); return; }
const writeStream = sftp.createWriteStream(remotePath);
writeStream.write(content);
writeStream.end();
writeStream.on('close', () => callback(null));
writeStream.on('error', (e) => callback(e));
});
});
}
function uploadDirectory(sftp, localDir, remoteDir, callback) {
fs.readdir(localDir, { withFileTypes: true }, (err, entries) => {
if (err) { callback(err); return; }
let completed = 0;
let hasError = false;
entries.forEach(entry => {
const localPath = path.join(localDir, entry.name);
const remotePath = path.join(remoteDir, entry.name);
if (entry.isDirectory()) {
uploadDirectory(sftp, localPath, remotePath, (dirErr) => {
if (dirErr) { hasError = true; callback(dirErr); }
completed++;
if (completed === entries.length && !hasError) callback(null);
});
} else {
uploadFile(sftp, localPath, remotePath, (fileErr) => {
if (fileErr) { hasError = true; callback(fileErr); }
completed++;
if (completed === entries.length && !hasError) callback(null);
});
}
});
if (entries.length === 0) callback(null);
});
}
conn.on('ready', () => {
console.log('=== 删除旧的h5目录 ===');
conn.exec(`rm -rf ${remoteH5Dir}`, (err) => {
if (err) { console.log('ERR:', err); }
console.log('\n=== 上传H5目录 ===');
conn.sftp((err2, sftp) => {
if (err2) { console.log('SFTP ERR:', err2); conn.end(); return; }
uploadDirectory(sftp, localH5Dir, remoteH5Dir, (uploadErr) => {
if (uploadErr) {
console.log('上传失败:', uploadErr);
sftp.end();
conn.end();
return;
}
sftp.end();
console.log('H5目录上传成功');
console.log('\n=== 验证 ===');
conn.exec(`ls -la ${remoteH5Dir}/`, (err3, stream3) => {
if (err3) { console.log('ERR3:', err3); conn.end(); return; }
stream3.on('data', (d) => console.log(d.toString()));
stream3.on('close', () => {
console.log('\n=== 重启Nginx ===');
conn.exec('/www/server/nginx/sbin/nginx -s reload', (err4, stream4) => {
if (err4) { console.log('ERR4:', err4); }
else { stream4.on('data', (d) => console.log(d.toString())); }
stream4.on('close', () => {
setTimeout(() => {
console.log('\n=== 测试 ===');
conn.exec('curl -s -I https://hs.yifenbao.cn/assets/index-B5v3elQl.js', (err5, stream5) => {
if (err5) { console.log('ERR5:', err5); }
else { stream5.on('data', (d) => console.log(d.toString())); }
stream5.on('close', () => {
console.log('\n=== 完成 ===');
conn.end();
});
});
}, 2000);
});
});
});
});
});
});
});
});
conn.connect({ host: 'hs.yifenbao.cn', port: 22, username: 'root', password: 'Torch1112' });