Compare commits
2 Commits
a4f4078551
...
eeff7271a1
| Author | SHA1 | Date | |
|---|---|---|---|
| eeff7271a1 | |||
| 92147b39ec |
@ -119,60 +119,40 @@ class SFTPService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
({ conn, sftp } = await this.createConnection(hostConfig));
|
({ conn, sftp } = await this.createConnection(hostConfig));
|
||||||
|
const filename = path.basename(remotePath);
|
||||||
|
const self = this;
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 获取文件大小
|
// 使用 fastGet 方法进行下载,更加可靠
|
||||||
sftp.stat(remotePath, (err, stats) => {
|
sftp.fastGet(remotePath, localPath, {
|
||||||
if (err) {
|
concurrency: 1, // 单线程下载,更稳定
|
||||||
conn.end();
|
chunkSize: 32768, // 32KB 块大小
|
||||||
reject(err);
|
step: function (transferred, chunk, total) {
|
||||||
return;
|
const percent = Math.round((transferred / total) * 100);
|
||||||
}
|
if (self.progressCallback) {
|
||||||
|
self.progressCallback({
|
||||||
const totalSize = stats.size;
|
|
||||||
let downloadedSize = 0;
|
|
||||||
const filename = path.basename(remotePath);
|
|
||||||
|
|
||||||
// 创建读写流
|
|
||||||
const readStream = sftp.createReadStream(remotePath);
|
|
||||||
const writeStream = fs.createWriteStream(localPath);
|
|
||||||
|
|
||||||
readStream.on('data', (chunk) => {
|
|
||||||
downloadedSize += chunk.length;
|
|
||||||
const percent = Math.round((downloadedSize / totalSize) * 100);
|
|
||||||
if (this.progressCallback) {
|
|
||||||
this.progressCallback({
|
|
||||||
type: 'download',
|
type: 'download',
|
||||||
filename,
|
filename,
|
||||||
percent,
|
percent,
|
||||||
transferred: downloadedSize,
|
transferred,
|
||||||
total: totalSize,
|
total,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}, (err) => {
|
||||||
readStream.on('error', (err) => {
|
|
||||||
writeStream.destroy();
|
|
||||||
conn.end();
|
conn.end();
|
||||||
fs.unlink(localPath, () => { });
|
if (err) {
|
||||||
|
// 删除可能不完整的文件
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(localPath);
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略删除失败
|
||||||
|
}
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
writeStream.on('error', (err) => {
|
|
||||||
readStream.destroy();
|
|
||||||
conn.end();
|
|
||||||
fs.unlink(localPath, () => { });
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 使用 'finish' 事件确保数据完全写入磁盘
|
|
||||||
writeStream.on('finish', () => {
|
|
||||||
conn.end();
|
|
||||||
resolve({ success: true, localPath });
|
resolve({ success: true, localPath });
|
||||||
});
|
});
|
||||||
|
|
||||||
readStream.pipe(writeStream);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { success: false, error: err.message };
|
return { success: false, error: err.message };
|
||||||
@ -187,50 +167,34 @@ class SFTPService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
({ conn, sftp } = await this.createConnection(hostConfig));
|
({ conn, sftp } = await this.createConnection(hostConfig));
|
||||||
|
const filename = path.basename(localPath);
|
||||||
|
const self = this;
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const stats = fs.statSync(localPath);
|
// 使用 fastPut 方法进行上传,更加可靠
|
||||||
const totalSize = stats.size;
|
sftp.fastPut(localPath, remotePath, {
|
||||||
let uploadedSize = 0;
|
concurrency: 1, // 单线程上传,更稳定
|
||||||
const filename = path.basename(localPath);
|
chunkSize: 32768, // 32KB 块大小
|
||||||
|
step: function (transferred, chunk, total) {
|
||||||
// 创建读写流
|
const percent = Math.round((transferred / total) * 100);
|
||||||
const readStream = fs.createReadStream(localPath);
|
if (self.progressCallback) {
|
||||||
const writeStream = sftp.createWriteStream(remotePath);
|
self.progressCallback({
|
||||||
|
|
||||||
readStream.on('data', (chunk) => {
|
|
||||||
uploadedSize += chunk.length;
|
|
||||||
const percent = Math.round((uploadedSize / totalSize) * 100);
|
|
||||||
if (this.progressCallback) {
|
|
||||||
this.progressCallback({
|
|
||||||
type: 'upload',
|
type: 'upload',
|
||||||
filename,
|
filename,
|
||||||
percent,
|
percent,
|
||||||
transferred: uploadedSize,
|
transferred,
|
||||||
total: totalSize,
|
total,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}, (err) => {
|
||||||
readStream.on('error', (err) => {
|
|
||||||
writeStream.destroy();
|
|
||||||
conn.end();
|
conn.end();
|
||||||
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
writeStream.on('error', (err) => {
|
|
||||||
readStream.destroy();
|
|
||||||
conn.end();
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 使用 'finish' 事件确保数据完全写入
|
|
||||||
writeStream.on('finish', () => {
|
|
||||||
conn.end();
|
|
||||||
resolve({ success: true, remotePath });
|
resolve({ success: true, remotePath });
|
||||||
});
|
});
|
||||||
|
|
||||||
readStream.pipe(writeStream);
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { success: false, error: err.message };
|
return { success: false, error: err.message };
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user