Nodejs - 将所有文件从 ftp 下载到本地文件夹并移动到另一个 ftp 文件夹的脚本
Nodejs - script that download all file from ftp to local folder and move on to another ftp folder
我正在尝试下载 FTP 站点上特定文件夹中的所有文件。该文件夹名为“IN”(如示例代码所示)并包含许多 .csv 文件。
要求是这样的:
- 将 IN 文件夹中存在的所有 csv 下载到本地文件夹
- 将它们从 FTP 上的 IN 文件夹移动到 ftp 文件夹上的 ARCHIVE 文件夹
- 将所有 csv 文件合并到新的 csv 中,并导入 csv 的所有内容
我卡在第二点了。我使用 promise-ftp 来完成这个过程,这里是我的代码:
const fs = require("fs");
const Client = require("promise-ftp");
const sftp = new Client();
sftp
.connect({
host: "xxxxx",
port: 21,
user: "xxxx",
password: "xxxxx",
})
.then(() => {
console.log("connected");
// will return an array of objects with information about all files in the remote folder
return sftp.list("/htdocs/IN");
})
.then(async (data) => {
// data is the array of objects
len = data.length;
// x is one element of the array
await data.forEach((x) => {
let remoteFilePath = "/htdocs/IN/" + x.name;
if (x.type === "-") {
console.log(x.name);
sftp
.get(remoteFilePath)
.then((stream) => {
console.log("---------");
console.log(x.name);
return new Promise(function (resolve, reject) {
stream.once("close", resolve);
stream.once("error", reject);
stream.pipe(fs.createWriteStream("IN/" + x.name));
});
})
.then(() =>{
sftp
.rename("/htdocs/IN/" + x.name, "/htdocs/OUT/" + x.name)
.then(function () {
console.log("rinominato");
})
console.log("qui cancello: " + x.name);
});
}
});
}).then(() => {
sftp.end();
})
.catch((err) => {
console.log(err, "catch error");
});
现在这个脚本下载了我本地存储中的所有文件,但是当我试图将它重命名为另一个文件夹时,我收到这个错误:
Unhandled rejection FtpConnectionError: can't perform 'rename' command when connection status is: disconnecting
我认为我在放置 sftp.close 函数的位置上犯了一些错误,但我是 node.js 的新手。
任何人都可以帮助我更好地理解我错在哪里?
添加了新版本 的代码,其中包含更多异步和等待,但仍然无法正常工作:
const fs = require("fs");
const Client = require("promise-ftp");
const ftp = new Client();
const downloadAndStoreFile = async () => {
await ftp.connect({
host: "xxxx",
port: 21,
user: "xxx",
password: "xxx",
});
console.log ('connected');
let data = await ftp.list('/htdocs/IN');
data = data.filter(function (file) {
return file.type === "-" ? file : null;
});
console.log(data);
data.forEach((file)=>{
if (file.type === '-'){
//console.log(file.name);
const operation = async () => {
console.log(file.name);
const stream = await ftp.get("/htdocs/IN/" + file.name);
const streamResult = await stream.pipe(fs.createWriteStream("IN/" + file.name));
const renameResult = await ftp.rename("/htdocs/IN/" + file.name, "/htdocs/OUT/" + file.name);
};
operation();
}
});
await ftp.end();
};
downloadAndStoreFile();
谢谢
请尝试使用 await 方式来做这样的事情:
const fs = require("fs");
const Client = require("promise-ftp");
const sftp = new Client();
sftp
.connect({
host: "XXXX",
port: 21,
user: "XXX",
password: "XXX",
})
.then(() => {
console.log("connected");
// will return an array of objects with information about all files in the remote folder
return sftp.list("/htdocs/IN");
})
.then(async(data) => {
// data is the array of objects
len = data.length;
for (let i = 0; i < len; i++) {
let x = data[i]; // x is one element of the array
let remoteFilePath = "/htdocs/IN/" + x.name;
if (x.type === "-") {
console.log(x.name);
let stream = sftp.get(remoteFilePath);
console.log("---------");
console.log(x.name);
await stream.pipe(fs.createWriteStream("IN/" + x.name));
await sftp.rename("/htdocs/IN/" + x.name, "/htdocs/OUT/" + x.name)
console.log("rinominato");
console.log("qui cancello: " + x.name);
}
}
}).then(() => {
sftp.end();
})
.catch((err) => {
console.log(err, "catch error");
});
您遇到的错误非常具有描述性:
Unhandled rejection FtpConnectionError: can't perform 'rename' command when connection status is: disconnecting
我们可以从中得出结论,当客户端尝试断开连接时,正在调用 rename
。问题在于在 forEach 循环中进行异步调用,因为您在结束连接之前没有等待它们解决。
一种可能的解决方案是将操作映射到 promise 数组并调用 Promise.all
。
Promise.all(
data
.filter((file) => file.type === "-")
.map((file) => {
const operation = async () => {
const stream = await ftp.get("/htdocs/IN/" + file.name);
const streamResult = await stream.pipe(
fs.createWriteStream("IN/" + file.name)
);
const renameResult = await ftp.rename(
"/htdocs/IN/" + file.name,
"/htdocs/OUT/" + file.name
);
};
return operation();
})
);
我正在尝试下载 FTP 站点上特定文件夹中的所有文件。该文件夹名为“IN”(如示例代码所示)并包含许多 .csv 文件。
要求是这样的:
- 将 IN 文件夹中存在的所有 csv 下载到本地文件夹
- 将它们从 FTP 上的 IN 文件夹移动到 ftp 文件夹上的 ARCHIVE 文件夹
- 将所有 csv 文件合并到新的 csv 中,并导入 csv 的所有内容
我卡在第二点了。我使用 promise-ftp 来完成这个过程,这里是我的代码:
const fs = require("fs");
const Client = require("promise-ftp");
const sftp = new Client();
sftp
.connect({
host: "xxxxx",
port: 21,
user: "xxxx",
password: "xxxxx",
})
.then(() => {
console.log("connected");
// will return an array of objects with information about all files in the remote folder
return sftp.list("/htdocs/IN");
})
.then(async (data) => {
// data is the array of objects
len = data.length;
// x is one element of the array
await data.forEach((x) => {
let remoteFilePath = "/htdocs/IN/" + x.name;
if (x.type === "-") {
console.log(x.name);
sftp
.get(remoteFilePath)
.then((stream) => {
console.log("---------");
console.log(x.name);
return new Promise(function (resolve, reject) {
stream.once("close", resolve);
stream.once("error", reject);
stream.pipe(fs.createWriteStream("IN/" + x.name));
});
})
.then(() =>{
sftp
.rename("/htdocs/IN/" + x.name, "/htdocs/OUT/" + x.name)
.then(function () {
console.log("rinominato");
})
console.log("qui cancello: " + x.name);
});
}
});
}).then(() => {
sftp.end();
})
.catch((err) => {
console.log(err, "catch error");
});
现在这个脚本下载了我本地存储中的所有文件,但是当我试图将它重命名为另一个文件夹时,我收到这个错误:
Unhandled rejection FtpConnectionError: can't perform 'rename' command when connection status is: disconnecting
我认为我在放置 sftp.close 函数的位置上犯了一些错误,但我是 node.js 的新手。
任何人都可以帮助我更好地理解我错在哪里?
添加了新版本 的代码,其中包含更多异步和等待,但仍然无法正常工作:
const fs = require("fs");
const Client = require("promise-ftp");
const ftp = new Client();
const downloadAndStoreFile = async () => {
await ftp.connect({
host: "xxxx",
port: 21,
user: "xxx",
password: "xxx",
});
console.log ('connected');
let data = await ftp.list('/htdocs/IN');
data = data.filter(function (file) {
return file.type === "-" ? file : null;
});
console.log(data);
data.forEach((file)=>{
if (file.type === '-'){
//console.log(file.name);
const operation = async () => {
console.log(file.name);
const stream = await ftp.get("/htdocs/IN/" + file.name);
const streamResult = await stream.pipe(fs.createWriteStream("IN/" + file.name));
const renameResult = await ftp.rename("/htdocs/IN/" + file.name, "/htdocs/OUT/" + file.name);
};
operation();
}
});
await ftp.end();
};
downloadAndStoreFile();
谢谢
请尝试使用 await 方式来做这样的事情:
const fs = require("fs");
const Client = require("promise-ftp");
const sftp = new Client();
sftp
.connect({
host: "XXXX",
port: 21,
user: "XXX",
password: "XXX",
})
.then(() => {
console.log("connected");
// will return an array of objects with information about all files in the remote folder
return sftp.list("/htdocs/IN");
})
.then(async(data) => {
// data is the array of objects
len = data.length;
for (let i = 0; i < len; i++) {
let x = data[i]; // x is one element of the array
let remoteFilePath = "/htdocs/IN/" + x.name;
if (x.type === "-") {
console.log(x.name);
let stream = sftp.get(remoteFilePath);
console.log("---------");
console.log(x.name);
await stream.pipe(fs.createWriteStream("IN/" + x.name));
await sftp.rename("/htdocs/IN/" + x.name, "/htdocs/OUT/" + x.name)
console.log("rinominato");
console.log("qui cancello: " + x.name);
}
}
}).then(() => {
sftp.end();
})
.catch((err) => {
console.log(err, "catch error");
});
您遇到的错误非常具有描述性:
Unhandled rejection FtpConnectionError: can't perform 'rename' command when connection status is: disconnecting
我们可以从中得出结论,当客户端尝试断开连接时,正在调用 rename
。问题在于在 forEach 循环中进行异步调用,因为您在结束连接之前没有等待它们解决。
一种可能的解决方案是将操作映射到 promise 数组并调用 Promise.all
。
Promise.all(
data
.filter((file) => file.type === "-")
.map((file) => {
const operation = async () => {
const stream = await ftp.get("/htdocs/IN/" + file.name);
const streamResult = await stream.pipe(
fs.createWriteStream("IN/" + file.name)
);
const renameResult = await ftp.rename(
"/htdocs/IN/" + file.name,
"/htdocs/OUT/" + file.name
);
};
return operation();
})
);