mscdex / node-ftp

An FTP client module for node.js
MIT License
1.13k stars 246 forks source link

Duplicated uploads #197

Open the-noob opened 6 years ago

the-noob commented 6 years ago

I have a watcher on a folder that is supposed to upload all new files.

watcher.on('add', (pathAndFilename) => {
  logger.info(`File '${pathAndFilename}' was added`);

  ftpClient.on('ready', () => {
    ftpClient.put(pathAndFilename, pathAndFilename.split(path.sep).pop(), (error) => {
      if (error) {
        logger.error(`Error transferring over FTP '${pathAndFilename}'`, error);
      } else {
        logger.info(`File successfully transferred over FTP '${pathAndFilename}'`);
      }
      ftpClient.end();
    });
  });

  ftpClient.connect({
    host: ftpHost,
    port: ftpPort,
    user: ftpUser,
    password: ftpPassword,
  });
})

Every time a new file is being uploaded the FTP reuploads the previous ones. i.e.

start ftp
add `file1` -> ftp uploads `file1`
add `file2` -> ftp uploads `file1`, `file2`
add `file3` -> ftp uploads `file1`, `file2`, `file3`
...
icetee commented 6 years ago

I do not think you should close the FTP connection if you are watching it.

the-noob commented 6 years ago

Maybe it's not clear from my snippet but I am watching a local folder and then upload any new files being added to that folder. As it might be hours in between the connection needs to be closed.

icetee commented 6 years ago

The problem is to subscribe to the event every time you connected FTP. Bad way.

icetee commented 6 years ago

Check this.

const EventEmitter = require('events');
const fs = require('fs');
const Client = require('../lib/connection');
const config = { ... };

const client = new Client();
const emitter = new EventEmitter();
const watchPath = './__folder/';
const uploadList = [];

const ready = () => client.cwd('/keymaps/', () => emitter.emit('connected'));

client.on('error', (err) => {
  console.error('ERROR: ', err);
});

client.on('close', (err) => {
  console.error('CLOSE: ', err);
});

const connected = () => {
  const upload = (filename, key) => {
    client.put(watchPath + filename, filename, (err) => {
      if (err) throw err;

      console.log('Uploaded: ', filename);
      delete uploadList[key]

      client.list((err, list) => {
        if (err) throw err;
        console.log(list);
      });
    });
  };

  uploadList.forEach(upload);
  client.end();
};

fs.watch(watchPath, { encoding: 'utf8' }, (eventType, filename) => {
  if (eventType === 'change') {
    uploadList.push(filename);
    emitter.emit('upload');
  }
});

client.on('ready', ready);
emitter.on('upload', (eventType, filename) => client.connect(config));
emitter.on('connected', connected);
icetee commented 6 years ago

I hope I helped.

the-noob commented 6 years ago

I've just used another library that behaves as expected.

amit1989patel commented 6 years ago

can you suggest what another library you have used because I am facing the same problem?

the-noob commented 6 years ago

jsftp