GraphQL: ошибка при разрешении обещаний во время загрузки файла

Итак, я работал с загрузками GraphQL, и прежде чем изложить свою проблему, вот обзор технического стека, который я использую:

Бэкенд: Mongoose, Express, Apollo, GraphQL

Фронтенд: VueJS, Apollo, GraphQL

Я использую Клиент загрузки Apollo для отправки файлов Загрузить на сторону сервера от клиента. Поскольку я отправляю от клиента список файлов типа скаляр Загрузить, я получаю список обещаний, которые необходимо разрешить. При использовании Обещание.все() я получаю следующую ошибку (которой, как ни странно, раньше не было, и я не знаю почему). Если я загружаю более одного файла, первый файл просто где-то теряется, а второй файл загружается .... Но это не всегда. Иногда этого не происходит. Может быть, я не решаю или не угождаю обещаниям должным образом. Обратите внимание, что мне также нужно сохранить имя файла в MongoDB через Mongoose.

    { BadRequestError: Request disconnected during file upload stream parsing.
     at IncomingMessage.request.once (F:\repos\pushbox\node_modules\graphql-upload\lib\processRequest.js:245:35)
     at Object.onceWrapper (events.js:285:13)
     at IncomingMessage.emit (events.js:197:13)
     at resOnFinish (_http_server.js:583:7)
     at ServerResponse.emit (events.js:202:15)
     at onFinish (_http_outgoing.js:683:10)
     at processTicksAndRejections (internal/process/next_tick.js:74:9)
   message: 'Request disconnected during file upload stream parsing.',
   expose: true,
   statusCode: 499,
   status: 499 }

У меня есть тег ввода HTML-файла, который принимает несколько файлов, и я использую мутацию:

async uploadFiles() {
  // Check if input tag is empty
  if (this.files.length === 0) {
    this.uploadErrorAlert = true;
    return;
  }

  // Mutation
  this.isUploading = true;
  await this.$apollo.mutate({
    mutation: UPLOAD_FILES,
    variables: {
      files: this.files,
      id: this.selectedCard.id,
    },
  })
    .then(() => {
    // clear files from the input tag
      this.files = '';
      this.$refs.selectedFiles.value = '';
      this.isUploading = false;
    })
    .catch((err) => {
      console.error(err);
    });
},

И, наконец, резолвер на сервере:

/**
 * Uploads files sent on disk and saves
 * the file names in the DB
 *
 * @param {Object} attachments - List of files for a card
 *
 * @return {Boolean} - true if upload is
 * successful
 */
uploadFiles: async (_, attachments, { controllers }) => {
  Promise.all(attachments.files.map(async (file) => {
    const { createReadStream, filename } = await file;
    const stream = createReadStream();

    /**
     * We need unique names for every file being uploaded,
     * so we use the ID generated by MongoDB and concat it
     * to the filename sent by the user.
     *
     * Therefore we instantiate an attachment object to get an ID
     */
    const attachment = await controllers.attachment.add({ id: attachments.id, file: '' });
    const newFileName = `${attachment.id}_${filename}`;
    const path = `${process.env.UPLOAD_DIR}/${newFileName}`;

    await controllers.attachment.update({
      id: attachment.id,
      file: newFileName,
    });

    console.info(`reached for ${path}`);
    // Attempting to save file in server
    return new Promise((resolve, reject) => stream
      .pipe(createWriteStream(path))
      .on('finish', () => resolve())
      .on('error', (error) => {
        console.info('dude?');
        if (stream.truncated) {
          // Delete the truncated file
          unlinkSync(path);
        }
        reject(error);
      }));
  })).then(() => {
    pubsub.publish(ATTACHMENTS_ADDED, { attachmentsChanged: controllers.attachment.getAll() });
  }).catch((err) => {
    console.info(err);
  });
},

Любая помощь будет оценена по достоинству!

Я думаю, что может возникнуть проблема с отправкой файла на серверную часть. Обычно, чтобы загрузить файл и отправить его на сервер, вы должны использовать объект formData. Вы должны просмотреть каждый файл и добавить его как свойство. const fd = новые данные формы(); this.files.forEach((файл) => { fd.append('файлы', файл)}

Mohit Tilwani 18.03.2019 23:56

Итак, я только что попробовал это, и я ничего не получаю на бэкэнде. Когда я отправляю его без formData, т.е. просто отправляю это.файлы, то я получаю файлы. консоль для formData в Backend: { id: '5c8b7b5959fa58d85041ba34', files: [ {} ] } консоль для this.files в Backend: { id: '5c8b7b5959fa58d85041ba34', files: [ Promise { [Object] }, Promise { [Object] }, Promise { [Object] } ] }

Edd Chang 19.03.2019 09:33
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
2
2 790
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, я не знаю, как я пропустил Эта проблема здесь, но это решение! Проблема связана с модулем, который я использую, на форуме проблем github.

Таким образом, проблема решается использованием await перед функцией Promise.all(). Итак, теперь код внутри преобразователя uploadFiles выглядит так:

await Promise.all(attachments.files.map(async (file) => {
    const { createReadStream, filename } = await file;
    const stream = createReadStream();

    /**
     * We need unique names for every file being uploaded,
     * so we use the ID generated by MongoDB and concat it
     * to the filename sent by the user.
     *
     * Therefore we instantiate an attachment object to get an ID
     */
    const attachment = await controllers.attachment.add({ id: attachments.id, file: '' });
    const newFileName = `${attachment.id}_${filename}`;
    const path = `${process.env.UPLOAD_DIR}/${newFileName}`;

    await controllers.attachment.update({
      id: attachment.id,
      file: newFileName,
    });

    console.info(`reached for ${path}`);
    // Attempting to save file in server
    return new Promise((resolve, reject) => stream
      .pipe(createWriteStream(path))
      .on('finish', () => resolve())
      .on('error', (error) => {
        console.info('dude?');
        if (stream.truncated) {
          // Delete the truncated file
          unlinkSync(path);
        }
        reject(error);
      }));
  })).then(() => {
    pubsub.publish(ATTACHMENTS_ADDED, { attachmentsChanged: controllers.attachment.getAll() });
  }).catch((err) => {
    console.info(err);
  });

Другие вопросы по теме