I'm trying to resize an image using Sharp module and then render it on GET request path.
fs.readFile(`${imageDir}${filename}.jpg`, (err, img) => {
if (err) { // File name doesn't match existing images
res.send('Error: No image found');
}
// Resizing image and saving it on file system
sharp(img)
.resize(Number(width), Number(height))
.toFile(`${thumbDir}${filename}-${width}-${height}.jpg`) // ---> THIS HERE DOES res.end() or res.send()
.then(info => {
// Rendering image on page
fs.readFile(`${thumbDir}${filename}-${width}-${height}.jpg`,(err, img) => {
if (err) throw err;
res.end(img); // -----> THIS ONE DOESN'T WORK
});
});
});
I want to stop sharp().resize().toFile() from "send" or "end" the response so I can "end" with resized image.
I can't remember what I did but something made res.end(img) line work and I got an error that I can't set header after response is sent.
P.S. I'm so sorry for any badly explained sections, please feel free to ask for any clarification.
Even without knowing all of the context, I would recommend switching to the fs/promises
APIs so you don't need to mix fs
's callback-style asynchronicity with Sharp's promises. Then you can make your request handler async
:
const fsp = require("fs/promises");
app.get("...", async (req, res) => {
// (... read width, height, filename here...)
try {
const img = await fsp.readFile(`${imageDir}${filename}.jpg`);
const thumbName = `${thumbDir}${filename}-${width}-${height}.jpg`;
await sharp(img).resize(Number(width), Number(height)).toFile(thumbName);
const thumb = await fsp.readFile(thumbName);
// TODO: add correct content-type, etc. headers
res.end(thumb);
} catch (err) {
// TODO: improve error handling
console.error(err);
res.status(400).end("Error processing file");
}
});
PS: be sure to sanitize filename
, width
and height
if they're user inputs; the above code is currently wide open to various file system traversal vulnerabilities.