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!
6
2 Answers
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 streamToString = (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 image = await streamToString(createReadStream())
const sharpImage = sharp(image)
}
}
Apollo recommends using signed URLs rather than uploading files via mutations. https://www.apollographql.com/blog/backend/file-uploads/file-upload-best-practices/
This is due to CSRF risks and performance impacts, especially as an app scales. For an app which properly handles the CSRF risks, uploading a file via a mutation should be fine.
stream != buffer ?
May 28, 2021 at 9:53
@xadm Thanks for your input. I know that stream is not a buffer. I was just trying to provide some example to work with. I am trying to understand how to use
createReadStream
and process the image withsharp
May 28, 2021 at 9:58
check args … file is ready as awaited (and if passed corectly, of course) … console.log image or file … stackoverflow.com/a/61452904/6124657
May 28, 2021 at 10:05
@xadm when I pass the awaited file result to sharp, I still get
[Error: Input file is missing]
.I added the result of theconsole.log
of the awaited file to my questionMay 28, 2021 at 10:22
it seams you can use stream … stackoverflow.com/a/61786860/6124657
May 28, 2021 at 10:49