Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send multiple files #66

Closed
efsantana opened this issue Nov 11, 2013 · 6 comments
Closed

Send multiple files #66

efsantana opened this issue Nov 11, 2013 · 6 comments

Comments

@efsantana
Copy link

I'm trying to send multiple files to the ftp server and I'm usually losing connection after sending the first file. What's the best way to send more than one file to an ftp server.

I'm getting the files as base 64 strings through web sockets using socket.io and trying to send them using the put method.

@xiaomeng
Copy link

I tried to use Ftp.raw.mput(), seems it is not supported by jsftp?

@evanplaice
Copy link

I'm having the same issue, except I'm using `ftp.put()'

Note: The following code is from the node-ftpsync project.

Here's my upload function:

  // upload a file to the remote server
  upload: function(file, callback) {
    var local = settings.local + file;
    var remote = settings.remote + file;
    fs.readFile(local, function(err, buffer) {
      if(err) {
        console.error(err);
        callback(err);
      }
      else {
        ftp.put(buffer, remote, function(err) {
          if (err) {
            console.error(err);
            callback(err);
          }
          else {
            console.log(file + " - uploaded successfuly");
            callback();
          }
        });
      }
    });
  },
  • ftp holds the jsftp instance.

The number of parallel connections are limited via async.mapLimit()

        async.mapLimit(sync.update, settings.connections, utils.upload, function (err) {
          if (err) {
            callback(err, 'updates failed');
          }
          else {
            callback(null, 'updates complete');
          }
        });
  • sync.update - contains the list of files queued for upload
  • settings.connections - is the max number of connections
  • utils.upload - is the upload function I posted above.

For each item in sync.update it calls the utils.upload() function but the maximum number of uploads running in parallel is limited to whatever settings.connections is set to. Currently it only works if settings.connections is set to 1.

It would make sense that a jsftp instance only has the ability to buffer one connection at a time.

If that's the case then maybe it's possible to overcome the limitation by creating a new jsftp instance for each connection by cloning the template jsftp instance each time an action (ex upload) is performed. In theory, if the instance is cloned into a local variable the memory used by the clone should be recovered when the action is complete and the local scope is closed.

Ex:

  upload: function(file, callback) {
    var newFTP = new ftp();
    var local = settings.local + file;
    var remote = settings.remote + file;
    fs.readFile(local, function(err, buffer) {
      if(err) {
        console.error(err);
        callback(err);
      }
      else {
        newFtp.put(buffer, remote, function(err) {
          if (err) {
            console.error(err);
            callback(err);
          }
          else {
            console.log(file + " - uploaded successfuly");
            callback();
          }
        });
      }
    });
  },

@evanplaice
Copy link

My assumptions seem to have been correct.

Simply creating a copy of the main ftp instance didn't work and I don't want to delve into the dark art of deep cloning objects so I chose the simpler approach.

Instead I just created a fresh jsftp instance for each upload.

  upload: function(file, callback) {
    var ftp = new jsftp({
      host: settings.host,
      port: settings.port,
      user: settings.user,
      pass: settings.pass
    });
    var local = settings.local + file;
    var remote = settings.remote + file;
    fs.readFile(local, function(err, buffer) {
      if(err) {
        console.error(err);
        callback(err);
      }
      else {
        newFtp.put(buffer, remote, function(err) {
          if (err) {
            console.error(err);
            callback(err);
          }
          else {
            console.log(file + " - uploaded successfuly");
            callback();
          }
        });
      }
    });
  },

For quicker tasks such as rmdir, mkdir, and delete I just limit to one connection and use the main ftp instance. For uploads, downloads I fire off a new jsftp instance for each connection.

I tested this uploading ten copies of a 8MB file with 2, 3, 4, 5, and 10 concurrent connections and it hasn't failed yet. The more connections I added, the more memory my application used but I didn't see any other noticeable side-effects.

IMHO, this issue is solved.

@mrameezraja
Copy link

does anyone able to solve the issue without creating a new instance for every file?

GochoMugo added a commit to forfuturellc/fpush that referenced this issue Aug 16, 2016
Bug:

    Handling the two tasks of deleting and putting files
    in parallel, on the same connection, causes issue
    as commands to handle each scenario are passed over
    and are persisted to the following actions.

    Since the same connection is used, we need some order
    in handling the files

Fix:

    The actions are handled in series. First, put then delete.
    Not parallel.

    Each of the files, in the actions, are handled in series.
    One file after the other. Not all at the same time.

References:

    * Sending multiple files: sergi/jsftp#66
@sergi sergi closed this as completed Oct 31, 2016
@JulienLeal
Copy link

This just happens yet. How I fix it ??

@juampi92
Copy link

juampi92 commented May 8, 2017

IDK if some of you figured it out, but in I had the same problem, and I tried using a mapSeries instead of parallel. Seems that one FTP session can only do one task at once. If you'd like parallelism, use multiple sessions (or sockets)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants