узел js загружает изображение и загружает на ftp: работает для одного, но не для двух изображений

#node.js

Вопрос:

 var ftpClient = new ftp();
var form = new formidable.IncomingForm();
form.parse(request, function(err, fields, files) {
    if (files.shoplogo.name) {
        var dimensions = sizeOf(files.shoplogo.path);
        console.log(dimensions.width   " x "   dimensions.height);
        if (dimensions.width > 255 || dimensions.height > 255 || dimensions.width < 145 || dimensions.height < 145) {
            response.send('<script>alert("Das Bild darf nicht größer 250x250 oder kleiner als 150x150 sein."); history.back(); </script>');
            return;
        }
        if (files.shoplogo.size > 200000) {
            response.send('<script>alert("Das Bild darf nicht größer als 150 kb sein."); history.back(); </script>');
            return;
        } else {
            var oldpath = files.shoplogo.path;
            ftpClient.on('ready', function() {
                ftpClient.put(oldpath, '/web/shopContent/'   'logo_'   fields.shopid   ".jpg", function(err, list) {
                    if (err) throw err;
                    ftpClient.end();
                });
            });
        }
    }
    if (files.shopcover.name) {
        var dimensions = sizeOf(files.shopcover.path);
        console.log(dimensions.width   " x "   dimensions.height);
        if (dimensions.width > 505 || dimensions.height > 505 || dimensions.width < 245 || dimensions.height < 245) {
            response.send('<script>alert("Das Bild darf nicht größer 500x500 oder kleiner als 250x250 sein."); history.back(); </script>');
            return;
        }
        if (files.shopcover.size > 200000) {
            response.send('<script>alert("Das Bild darf nicht größer als 150 kb sein."); history.back(); </script>');
            return;
        } else {
            var oldpath = files.shopcover.path;
            ftpClient.on('ready', function() {
                ftpClient.put(oldpath, '/web/shopContent/'   'cover_'   fields.shopid   ".jpg", function(err, list) {
                    if (err) throw err;
                    ftpClient.end();
                });
            });
        }
    }
    ftpClient.connect({
        'host': 'host',
        'user': 'user',
        'password': 'pw'
    });
});
 

Работая с нуля, мне удалось закодировать функцию, которая позволяет мне загружать изображения на мой сервер (с клиента), а затем загружать их на FTP-сервер.
Если пользователь выбирает по одному изображению за раз, все работает нормально, но загрузка обоих изображений прерывается.

Я думаю, проблема в том, как я справляюсь с подключением. Как я могу изменить код?

Комментарии:

1. Что вы имеете в виду под «перерывами»? Выбрасывает исключение, просто ничего не происходит, или что? Если это бросает, было бы полезно знать, в какой момент. Также обратите внимание, что если оба поля files.shopcover.name и files.shoplogo.name существуют, вы дважды попытаетесь закрыть ftp-соединение. Чтобы исправить это, я бы рекомендовал либо преобразовать эту функцию в функцию, основанную на обещаниях, либо вызывать ftpClient.connect() внутри каждого условия.

Ответ №1:

Вы не говорите, но я полагаю, что вы используете https://www.npmjs.com/package/ftp посылка.

Прежде всего, пожалуйста, ВЫСУШИТЕ (Не Повторяйтесь). Я извлек повторяющийся код в put_on_ftp() функцию (см. Ниже).

 // nothing special here, except that I've removed
// the `ftpClient.connect` call from the `form.parse()` function
// read along...

var form = new formidable.IncomingForm();
form.parse(request, function(err, fields, files) {
  if (files.shoplogo.name) {
    put_on_ftp(
      'logo_'   fields.shopid,
      files.shoplogo,
      {size: 200000, min_w: 145, max_w: 255, min_h: 145, max_h: 255},
    )
  }
  if (files.shopcover.name) {
    put_on_ftp(
      'cover_'   fields.shopid,
      files.shopcover,
      {size: 200000, min_w: 245, max_w: 255, min_h: 245, max_h: 255},
    )
  }
});
 

Затем в документах говорится, что

end() — (недействительно) — Закрывает соединение с сервером после выполнения любых/всех поставленных в очередь команд.

Обратите внимание на «любой» в этом пункте. Таким образом, это означает, что при загрузке первого из ваших изображений соединение прерывается, в то время как второе все еще находится в процессе.

Сам я не использовал этот пакет и даже не знаю, может ли он загружать несколько файлов параллельно… и я даже не уверен, правильно ли я угадал пакет, поэтому давайте воспользуемся самым простым подходом — просто откройте новое соединение для каждого файла.

 function put_on_ftp(file_name, file, limits)
  const dimensions = sizeOf(file.path);
  if (
    dimensions.width  > limits.max_w ||
    dimensions.height > limits.max_h ||
    dimensions.width  < limits.min_w ||
    dimensions.height < limits.min_h
  ) {
    response.send('some error');
    return;
  }
  if (file.size > limits.size) {
    response.send('some other error');
    return;
  } else {
    const ftpClient = new ftp();
    ftpClient.on('ready', function() {
      ftpClient.put(
        file.path,
        `/web/shopContent/${file_name}.jpg`,
        function(err) { // there is no `list` arguments
          if (err) throw err;
          ftpClient.end();
        });
      )
    })

    // -------------------------
    // do it here
    ftpClient.connect({
      'host': 'host',
      'user': 'user',
      'password': 'pw'
    });
    // -------------------------
  }
}
 

Также обратите внимание, что list в обратном вызове функции нет аргументов put() . И ты все равно им не пользуешься. Так что я бросил это дело.