Search code examples
node.jsgraphqlapollo-serversharp

How to Process Uploaded Image with Graphql Apollo with SharpJS in NodeJS?


I have a graphql mutation that gets an image from the frontend, and that then is processed and optimized on my server.

But I can't figure out how to pass my image to sharp.

Here is my code:

const Mutation = {
    createImage: async (_, { data }) => {
        const { file } = data
        const image = await file

        console.log(image)

        const sharpImage = sharp(image)
    }
}

I know the code doesn't work and sharp throws an error saying that the input is invalid. So how can I work with createReadStream and to create an instance of sharp?

When I console.log(image), here is what I see:

image {
  filename: 'image.png',
  mimetype: 'image/png',
  encoding: '7bit',
  createReadStream: [Function: createReadStream]
}

Thanks a lot in advance!


Solution

  • So I figured out the solution to my question.

    First, I found out that I needed to add scalar Upload to typeDefs.

    Then, I need to add a resolver for Upload like this:

    const { GraphQLUpload } = require('graphql-upload');
    
    const server = new ApolloServer({
      resolvers: {
        Upload: GraphQLUpload,
      }
    })
    

    Then in my resolver, here is what I had to do:

    // this is a utility function to promisify the stream and store the image in a buffer, which then is passed to sharp
    const streamToBuffer = (stream) => {
        const chunks = [];
        return new Promise((resolve, reject) => {
            stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
            stream.on('error', (err) => reject(err));
            stream.on('end', () => resolve(Buffer.concat(chunks)));
        })
    }
    
    const Mutation = {
        createImage: async (_, { data }) => {
            const { file } = data
            const { createReadStream } = await file
    
            const imageBuffer = await streamToBuffer(createReadStream())
    
            const sharpImage = sharp(imageBuffer)
        }
    }