简体   繁体   中英

Apollo-express-server passing only first Upload(file) and the rest are missing

I am using apollo-express server with GraphQL. I have a mutation where I pass files from front-end to back-end but I receive the file:{} object only for first one - for the other's I receive promise.

Here is my mutation declaration:

 extend type Mutation {
    createCase(input: CreateCase!, attachments: [Upload]): Case
  }

I simplified my implementation just to console.log the attachments:

Mutation: {
    createCase: async (
      parentValue: any,
      { input, attachments }: { input: CaseInterface; attachments: [File] },
      context: any
    ) => {
     
      console.log(attachments)
    }
}

I am passing the files from front-end like this:

const SEND_CASE = gql`
  mutation CreateCase($input: CreateCase!, $attachments: [Upload]) {
    createCase(input: $input, attachments: $attachments) {
      _id
    }
  }
`;

and the function usage:

 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,
      },
    });

the prop.creationData.attachments is looking normal: 在此处输入图像描述

The problem is that in my back-end I console.log(attachments) looks-like this:

[
  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> }
  }
]

The file in second Upload object is missing and the Promise there is pending. I cannot explain myself why is that. Also I have console.log the req.body and req.header if it is needed:

{
  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' +
    '}'
}

How can I have all my files in my backend to be like the first one received?

Both files are "there", but only one has finished uploading so far. They're both promises, though, so handling them both is the same. You just need to wait for the promises to resolve, and you should be fine.

According to the graphql-upload examples repo , assuming you have a method storeUpload like this one that processes a single file at a time, you can do this:

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.log(attachmentFilenames)
    }
  },
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM