5

I want to create image manipulation on the image fetched from the AWS S3 and would like to perform manipulation action on it. I am using stream to solve the problem of loading big files.

import AWS from 'aws-sdk'
import sharp from 'sharp'

const s3 = new AWS.S3()
const transformer = (w, res, next) =>
    sharp()
        .resize(w)
        .on('data', (data) => {
            console.log(data)
            res.write(data, 'binary')
        })
        .on('error', (err) => next(err))
        .on('end', () => {
            console.log('finished')
            res.status(200).end()
        })

const readStream = s3
    .getObject({
        Bucket: process.env.UPLOAD_BUCKET_NAME,
        Key: 'test.jpg'
        // Key: `${req.uid.uid}/${req.param('img')}`
    })
    .createReadStream()

const getImage = (w, res, next) => {
    readStream.pipe(transformer(w, res, next))
    readStream.on('error', (err) => next(err))
}

export default getImage

I am calling the getImage method on the route and this function serves images for the first time but when the second time the Image is requested, it throws Error: Input buffer contains unsupported image format

Prashant Singh
  • 137
  • 2
  • 9
  • Sounds pretty clear: even if the _filename_ claims it's a `.jpg`, that doesn't mean it _is_ a jpeg image. Check the stream: is it actually an image, or did you merely assume it would be, and it's actually the error output you get when requesting a non-existent resource? – Mike 'Pomax' Kamermans Aug 11 '20 at 00:54
  • @Mike'Pomax'Kamermans But the first time if you request the express route, then it shows the manipulated image. It only throws error on the second and following requests. – Prashant Singh Aug 11 '20 at 00:58
  • cool, but middleware for express takes the form `(req, res, next)`, not `(w, res, next)`, so you're not showing the whole story here. And if you're not using express, remember to say what you _are_ using. – Mike 'Pomax' Kamermans Aug 11 '20 at 01:14
  • Router is getting (req, res, next) and from there i am doing functions and sending the params from the req – Prashant Singh Aug 11 '20 at 01:38

1 Answers1

1

I found the solution.

const getImage = (req, res, next) => {
    const w = parseInt(req.params.w)
    const readStream = s3
        .getObject({
            Bucket: process.env.UPLOAD_BUCKET_NAME,
            Key: 'test.jpg'
        })
        .createReadStream()

    const transformer = (w) => sharp().resize(w)
    pipeline(readStream, transformer(w), res, (err) => {
        if (err) {
            next(err)
        }
    })
}
export default getImage

It was acting like that because it was not scoped to the request.

Prashant Singh
  • 137
  • 2
  • 9
  • This somewhat implies that you simply wrote a bad middleware signature, looked that up, realised it, and fixed it without stackoverflow being technically necessary here. In those cases it's a good idea to delete your question again. – Mike 'Pomax' Kamermans Aug 11 '20 at 16:01
  • 2
    I have left this question for those who might face the same problem and then they can fix that by just looking into the solution.@Mike'Pomax'Kamermans – Prashant Singh Aug 12 '20 at 05:18
  • 1
    Which is fine, as long as you realise that any problem you solved yourself because you effectively forgot to read the docs (so that your function used the right signature) means this wasn't a programming problem, but effectively just a typo, which is one of policies under which questions get closed right now. Others, like you, are expected to at least verify their code follows the APIs that they make use of, which in this case you hadn't, then you checked, then you corrected yourself. That's not something that "an answer" will help others with. They are expected to do the same. – Mike 'Pomax' Kamermans Aug 12 '20 at 15:32