Я использую сервер apollo-express с GraphQL. У меня есть мутация, при которой я передаю файлы из интерфейса в сервер, но получаю объект file:{} только для первого - для другого я получаю обещание.
Вот мое объявление мутации:
extend type Mutation {
createCase(input: CreateCase!, attachments: [Upload]): Case
}
Я упростил свою реализацию только для console.info вложений:
Mutation: {
createCase: async (
parentValue: any,
{ input, attachments }: { input: CaseInterface; attachments: [File] },
context: any
) => {
console.info(attachments)
}
}
Я передаю файлы из внешнего интерфейса следующим образом:
const SEND_CASE = gql`
mutation CreateCase($input: CreateCase!, $attachments: [Upload]) {
createCase(input: $input, attachments: $attachments) {
_id
}
}
`;
и использование функции:
createCase({
variables: {
input: {
description: props.creationData.description,
date: new Date().toDateString(),
priority: props.creationData.priority,
userId: props.creationData.userId,
categoryId: props.categories.map((el: any) => el._id),
signature: "",
type: props.casetype === "problem" ? 1 : 2,
},
attachments: props.creationData.attachments,
},
});
prop.creationData.attachments выглядит нормально:
Проблема в том, что в моем бэкэнде я console.info(attachments) выглядит так:
[
Upload {
resolve: [Function (anonymous)],
reject: [Function (anonymous)],
promise: Promise { [Object] },
file: {
filename: 'wa.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: [Function: createReadStream]
}
},
Upload {
resolve: [Function (anonymous)],
reject: [Function (anonymous)],
promise: Promise { <pending> }
}
]
Файл во втором объекте Upload отсутствует, а Promise находится на рассмотрении. Сам не могу объяснить, почему так. Также у меня есть console.info req.body и req.header, если это необходимо:
{
host: '192.168.1.152:3001',
connection: 'keep-alive',
'content-length': '51479',
accept: '*/*',
'apollo-require-preflight': 'true',
authorization: '',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryA2VfmoLeZm9NTXsk',
origin: 'http://localhost:3000',
referer: 'http://localhost:3000/',
'accept-encoding': 'gzip, deflate',
'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8,bg;q=0.7'
}
{
operationName: 'CreateCase',
variables: {
input: {
description: 'test',
date: 'Thu Jan 19 2023',
priority: 1,
userId: '630899dc48a9a14833398a7e',
categoryId: [Array],
signature: '',
type: 1
},
attachments: [ [Upload], [Upload] ]
},
query: 'mutation CreateCase($input: CreateCase!, $attachments: [Upload]) {\n' +
' createCase(input: $input, attachments: $attachments) {\n' +
' _id\n' +
' __typename\n' +
' }\n' +
'}'
}
Как я могу сделать так, чтобы все мои файлы в моем бэкэнде были такими же, как и у первого полученного?
Оба файла «есть», но пока только один из них загрузился. Однако они оба обещания, поэтому обращаться с ними обоими одинаково. Вам просто нужно дождаться разрешения обещаний, и все будет в порядке.
Согласно репозиторию graphql-upload , если у вас есть метод storeUpload
, подобный этому, который обрабатывает один файл за раз, вы можете сделать это:
const resolvers = {
Mutation: {
createCase: async (
parentValue: any,
{ input, attachments }: { input: CaseInterface; attachments: [File] },
context: any
) => {
const attachmentFilenames = [];
// Ensure an error storing one upload doesn’t prevent storing the rest.
for (const result of await Promise.allSettled(attachments.map(storeUpload))) {
if ("value" in result) {
attachmentFilenames.push(result.value);
} else {
// Realistically you would do more than just log an error.
console.error(`Failed to store upload: ${result.reason}`);
}
}
console.info(attachmentFilenames)
}
},
};