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



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Итак, я не знаю, как я пропустил Эта проблема здесь, но это решение! Проблема связана с модулем, который я использую, на форуме проблем 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);
});
Я думаю, что может возникнуть проблема с отправкой файла на серверную часть. Обычно, чтобы загрузить файл и отправить его на сервер, вы должны использовать объект formData. Вы должны просмотреть каждый файл и добавить его как свойство. const fd = новые данные формы(); this.files.forEach((файл) => { fd.append('файлы', файл)}