hnrch02 / multer-ftp

FTP storage engine for multer
MIT License
7 stars 3 forks source link

Upload stops working after some time. #2

Open krzywiecki opened 4 years ago

krzywiecki commented 4 years ago

Hello guys!

I'm using multer-ftp in my project and it works but always, after some time it stops working and is giving no error. Basically what's happening is: it works and it is uploading images to the FTP server but after some time I'm getting timeout error when I want to upload another file (it's happening really randomly from my perspective so I have no idea what's causing this problem). Then the only way is to restart node.js server. Then it works again for some time.

Do you have an idea what's happening or how can I debug it? I'd really appreciate any tip.

Thanks, Dominik

rcosta02 commented 4 years ago

Hey,

I'm also getting the same issue. Did someone find the solution?

Thanks Rafael

krzywiecki commented 4 years ago

Hey @rcosta02, yeah, I finally found a solution for this and forgot to write here.

So, basically in my case, the problem was that every time someone uploads a file the new FTP connection is opened but it was never closed. My server has limit of open connections so it simply stopped working after I reached the limit.

Code from my app:


const FTP = require('ftp');
const multer  = require('multer');
const FTPStorage = require('multer-ftp');

router.post('/avatar', (request, response) => {
    const ftpClient = new FTP();
    ftpClient.connect(config.ftp.connection);

    const upload = multer({
        storage: new FTPStorage({
            basepath: `${config.ftp.basepath}/avatars`,
            connection: ftpClient,
        })
    }).single('avatar'); // name of the frontend input field

    upload(request, response, (error) => {
        if (error) {
            return response.status(500).send({ error: 'Could not upload the image.' });
        }

        ftpClient.end();
        // do whatever you want with the response        
    });
});

Of course, you need to update ftp config.

Let me know if this helps :v:

tycheexchange commented 4 years ago

Dear @krzywiecki Hi Thanks for sharing this with us Would you please help me and let me know where can I close my ftp connection in my structure.


const multer = require("multer");
const FTPStorage = require('multer-ftp');

const storage = new FTPStorage({
    basepath: './public_html/artists-photos/',
    ftp: {
      host: 'xxxxxxx.com',  
      secure: false,
      user: process.env.FTP_USERNAME,  
      password: process.env.FTP_PASSWORD,
      port:21
    },
  destination: function(req, file,options, cb) {
    cb(null,'./xxxxxx/'+ Date.now() + "-" + file.originalname);
  },

});
const fileFilter = (req, file, cb) => {
  if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
    cb(null, true);
  } else {
    cb(null, false);
  }
};
const artistsPhotos = multer({
  storage: storage,
  fileFilter: fileFilter
});

module.exports = artistsPhotos;

Thank you

krzywiecki commented 4 years ago

Hi @tycheexchange,

First of all you need to import the 'ftp' package and use it as the FTP client. This is required to make it working.

tycheexchange commented 4 years ago

Dear @krzywiecki hi again my problem is that i dont know where should I close my ftp connection as you mentioned I have put ftp and my code now is ...

const FTP = require("ftp");
const multer = require("multer");
const FTPStorage = require("multer-ftp");

const ftpClient = new FTP();
ftpClient.connect({
  host: "xxxxxxxx.com",
  secure: false,
  user: process.env.FTP_USERNAME,
  password: process.env.FTP_PASSWORD,
  port: 21,
});

const storage = new FTPStorage({
  basepath: "./public_html/artists-photos/",
  destination: function (req, file, options, cb) {
    cb(
      null,
      "./public_html/artists-photos/" + Date.now() + "-" + file.originalname
    );
  },
});

const fileFilter = (req, file, cb) => {
  if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
    cb(null, true);
  } else {
    cb(null, false);
  }
};
const artistsPhotos = multer({
  storage: storage,
  fileFilter: fileFilter,
});

module.exports = artistsPhotos;

also my route is

router.route("/create-artist").post(auth,artistsPhotos.single("profile"),artistController.createArtist);

and here is my controller


 createArtist: async (req, res, next) => {
    const filename= req.file.path.split("/")[3];
    const newArtist = new Artist({
      profile: process.env.ARTISTS_FILE_SERVER_PATH + filename,
    });
    const artist = await newArtist.save();
    if (artist) {
      res.status(201).json({ message: "xxxxxxxxx" });
    } else {
      res
        .status(500)
        .json({ message: "xxxxxxxxxxxxxxxxxxxxxx" });
    }
  },

would you help me where should I close my ftp? Thanks

smtrz commented 4 years ago

Any leads ? i am also facing the similar issue @tycheexchange

Nezran commented 1 year ago

Hi People,

After many problems i think i found the solution. When using the FTP package you have to use it when ready. So :

  const ftpClient = new FTP();

  const connection = {
    host: 'xxx',
    username: 'xxx',
    user: 'xxx',
    password: 'xxx',
    port: 21,
  };

  ftpClient.connect(connection);

  var storage = new FTPStorage({
    basepath: '/', // base path for file uploads on the server
    connection: ftpClient,
    destination: function (req, file, options, callback) {
      const name = Date.now() + '-' + congId + '.jpeg';
      callback(null, '/' + name); // custom file destination, file extension is added to the end of the path
    },
  });

  // onReady FTP
  ftpClient.on('ready', function (e) {
    var upload = multer({ storage: storage }).array('file');

    // Then you upload only when ready => connected
    upload(req, res, function (err) {
      // Do your stuff
      //  On the doc of FTP you can use destroy() too, but i didnt try it.
      ftpClient.end();
      if (err) {
        // Err
      } else {
        // Good
      }
    });
  });

More info about the ftp package here : https://github.com/mscdex/node-ftp

NgoDuy2197 commented 1 year ago

Today i have the same issue.

After read "krzywiecki" explain. I use solution of "Nezran". It's seem be OK now.

My problem is that when you use new ftpStorage({ftp:.... The ftp property use for create connection into FTP but it's never close. I have 4 ftpStorage so when application start it create 4 connection and keep it forever.

ALERT: Use solution of "Nezran", you should be careful when catch error. If not, the connection exists until timeout or forever