Search code examples
node.jsaxiossharp

Downloading and resizing an image with Axios/Sharp


I'm currently trying to download an image using Axios and then resize the result and save it locally via Node in a GraphQL resolver.

This is the block of code I'm working with:

axios.get(url)
    .then((response) => {
        const { set, collector_number } = response.data;
        const sourceUrl = response.data.image_uris.border_crop;
        const filename = `${set}/${collector_number}.png`;
        axios.get(sourceUrl, { responseType: 'arraybuffer' })
            .then((res) => {
                console.log(`Resizing Image!`)
                sharp(res)
                    .resize(226, 321)
                    .toFile(`../cardimg/${filename}`)
                    .then(() => {
                        console.log(`Image downloaded and resized!`)
                    })
                    .catch((err) => {
                        console.log(`Couldn't process: ${err}`);
                    })
            })
    })

When I execute the code (via GraphQL Mutation), it throws an error saying that states: Input file is missing.

Not sure if it's misuse of Axios, or if I'm doing something wrong with Sharp.

Any suggestions? I was originally worried that I needed to mess with the format of the response coming from the HTTP request, but from what I can gather, I'm doing it correctly.

Thanks in advance!

I've used console.log to ensure that it's definitely grabbing an image and the URL is correct, so that's already been tested, so the sourceUrl is indeed grabbing an image, I'm just not sure how to properly do anything -with- the data that I'm grabbing.


Solution

  • axios returns full response body like status, headers, config. The response body is in .data key. So in your case it will be:

    axios.get(..).then((res) => { sharp(res.data)})
    

    Also, Promises inside promises are considered anti pattern, you can chain it easily.

    let fileName;
    axios.get(url)
      .then((response) => {
        const { set, collector_number } = response.data;
        const sourceUrl = response.data.image_uris.border_crop;
        filename = `${set}/${collector_number}.png`;
        return axios.get(sourceUrl, { responseType: 'arraybuffer' })
      })
      .then((res) => {
        console.log(`Resizing Image!`)
        return sharp(res.data)
          .resize(226, 321)
          .toFile(`../cardimg/${filename}`)
      })
      .then(() => {
        console.log(`Image downloaded and resized!`)
      })
      .catch((err) => {
        console.log(`Couldn't process: ${err}`);
      })