简体   繁体   English

Node.js [promise-ftp] - 从 FTP 下载多个文件时无法建立数据连接(错误:连接 ECONNREFUSED...)

[英]Node.js [promise-ftp] - Unable to make data connection (Error: connect ECONNREFUSED...) while downloading multiple files from FTP

I'm getting this error while trying to download multiple images from ftp using promise-ftp .尝试使用promise-ftpftp下载多个图像时出现此错误。 I'm able to see some images being downloaded before this error.我可以看到在出现此错误之前正在下载一些图像。

Unable to make data connection( Error: connect ECONNREFUSED...)无法建立数据连接(错误:连接 ECONNREFUSED...)

In my scenario, client sends specific directory paths of ftp from which all the images should be downloaded to server.在我的场景中,客户端发送 ftp 的特定目录路径,所有图像都应从中下载到服务器。

Here is my code:这是我的代码:

iniatially uploadData consists of data from client from which directory paths are obtained.最初uploadData包含来自客户端的数据,从中获取目录路径。

router.post("/addPhotos", async (req, res) => {
  try {
    let uploadData = req.body;

    if (!uploadData) {
      handleError("Error! Invalid data received.", res);
      return;
    }

    await getPhotosWithCaptionsAndPath(uploadData)
      .then(uDataWithCaptionsAndPath => {
        uploadData = uDataWithCaptionsAndPath;

        res.status(200).send({
          data: "Images Uploaded successfully!",
          success: true,
          error: null
        });
      })
      .catch(err => {
        handleError(err, res);
      });

    //insert uploadData to db . . .
  } catch (err) {
    handleError(err, res);
  }
});

getPhotosWithCaptionsAndPath = uploadData => {
  return new Promise(async (resolve, reject) => {
    try {
      let output = [];
      let fileCount = 0;

      //get total # of images in all directories
      await getfileCount(uploadData)
        .then(fc => (fileCount = fc))
        .catch(err => reject(err));

      //download images and generate output array for db rows
      const ftp = new PromiseFtp();
      await ftp
        .connect({
          host: env.ftp.host,
          user: env.ftp.user,
          password: env.ftp.password
        })
        .then(serverMessage => {
          //looping through each directory
          uploadData.forEach(async (v, i) => {
            // calc directory path
            /* prettier-ignore */
            let uri = `/${
              v.schoolName
            }/${
              v.studentClass.toString()
            }-${
              v.studentSection
            }/${
              v.studentName
            }`;

            await ftp
              .list(uri, false)
              .then(list => {
                //looping through each image file
                list.forEach((val, index) => {
                  uploadFtpFile(ftp, uri, val, output)
                    .then(outputFromUFF => {
                      output = outputFromUFF;
                      if (fileCount === output.length) {
                        ftp.end();
                        resolve(output);
                      }
                    })
                    .catch(err => reject(err));
                });
              })
              .catch(err => reject(err));
          });
        });
    } catch (err) {
      reject(err);
    }
  });
};

uploadFtpFile = (ftp, uri, val, output) => {
  return new Promise((resolve, reject) => {
    try {
      ftp.get(uri + "/" + val.name).then(stream => {
        let fileName = `ph${Date.now()}.png`;
        let file = fs.createWriteStream("./uploads/" + fileName);
        output.push({
          url: fileName,
          caption: val.name.replace(/\.[^/.]+$/, "")
        });

        stream.pipe(file);
        stream.once("close", () => {
          resolve(output);
        });
        stream.once("error", reject);
      });
    } catch (err) {
      reject(err);
    }
  });
};

getfileCount = uploadData => {
  return new Promise((resolve, reject) => {
    try {
      let fileCount = 0;
      const ftpC = new PromiseFtp();
      ftpC
        .connect({
          host: env.ftp.host,
          user: env.ftp.user,
          password: env.ftp.password
        })
        .then(serverMessage => {
          uploadData.forEach(async (v, i) => {
            /* prettier-ignore */
            let uri = `/${
            v.schoolName
          }/${
            v.studentClass.toString()
          }-${
            v.studentSection
          }/${
            v.studentName
          }`;
            await ftpC
              .list(uri, false)
              .then(async list => {
                fileCount += list.length;
                if (i === uploadData.length - 1) resolve(fileCount);
              })
              .catch(err => reject(err));
          });
        })
        .catch(err => reject(err));
    } catch (err) {
      reject(err);
    }
  });
};

There is a limit that is applied to FTP, so its not a good idea to bulk upload/download stuff from FTP, you need to convert your foreach loops to for loops this will allow each file to be processed in sequence, this may delay your process, but will be fail safe. FTP 有一个限制,因此从 FTP 批量上传/下载内容不是一个好主意,您需要将foreach循环转换为for循环,这将允许按顺序处理每个文件,这可能会延迟您的过程,但将是故障安全的。

So you may change this snippet所以你可以改变这个片段

for (let  i = 0; i < list.length; i++) {
  let val = list[i]
  uploadFtpFile(ftp, uri, val, output)
  .then(outputFromUFF => {
     output = outputFromUFF;
     if (fileCount === output.length) {
        ftp.end();
        resolve(output);
     }
   })
   .catch(err => reject(err));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM