How to resize/compress image before uploading to cloud storage

Black Sulfur
Black Sulfur used Ask the Experts™
on
So, I have deployed what I have done on my project so far to Heroku only to discover that that any images you upload to their server are deleted periodically! Not super helpful.

https://help.heroku.com/K1PPS2WM/why-are-my-file-uploads-missing-deleted

So, that means I have to either store the images in the database which I don't want to do, or upload to a cloud server. Before setting this up, I was using sharp to resize and compress the uploaded image. So, I uploaded the file into memory, resized/compressed it and then wrote it to a new file. I am uploading to google cloud storage.

I have the upload to the cloud working but it is uploading the original image, not the resized one. I think that it is because the cloud upload isn't uploading the one from memory but rather the original uploaded file.

This is the route:

router.post(
  "/",
  heroController.uploadUserPhoto,
  heroController.resizeUserPhoto,
  heroController.sendUploadToGCS,
  heroController.updateHeroImg
); 

Open in new window


Controllers

// save image to memory instead of to disk
const multerStorage = multer.memoryStorage();

const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
});

// upload the image
exports.uploadUserPhoto = upload.single("bgImg");

//resize and compress image
exports.resizeUserPhoto = (req, res, next) => {
  if (!req.file) return next();

  req.file.filename = `hero-${Date.now()}.jpeg`;

  // get the image from memory
  sharp(req.file.buffer)
    .resize(1800, 948, {
      fit: sharp.fit.outside
    })
    .toFormat("jpeg")
    .jpeg({ quality: 80 })
    .toFile(`public/img/${req.file.filename}`);

  next();
};

Open in new window


const gc = new Storage({
  keyFilename: path.join(__dirname, "../someFile.json"),
  projectId: "something-here-123456"
});

const bucket = gc.bucket("myBucket");

function getPublicUrl(filename) {
  return `https://storage.googleapis.com/something-here-123456/${filename}`;
}

exports.sendUploadToGCS = (req, res, next) => {
  if (!req.file) {
    return next();
  }

  const gcsname = req.file.filename;
  const file = bucket.file(gcsname);

  const stream = file.createWriteStream({
    metadata: {
      contentType: req.file.mimetype
    },
    resumable: false
  });

  stream.on("error", err => {
    req.file.cloudStorageError = err;
    next(err);
  });

  stream.on("finish", () => {
    req.file.cloudStorageObject = gcsname;
    file.makePublic().then(() => {
      req.file.cloudStoragePublicUrl = getPublicUrl(gcsname);
      next();
    });
  });

  stream.end(req.file.buffer);
};

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
I don't think I have enough code to look at.
But besides that, why do you need to resize the pictures? Saving to Google Photos, means UNLIMITED FREE storage. (You're saving to Google Drive/Storage, this counts to your normal GMail storage limit)

Author

Commented:
I want to compress it for the frontend user. They should't have to download a 3.1mb image for a banner image. So, I want to compress it so they only have to download say 500kb instead.

Commented:
OK please post the rest of the code you have.

Author

Commented:
Which code are you looking for? That is all the code that handles the upload. It just needs to be changed to upload the resized image instead of the original image.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial