How to pass a unique uuid to each callback?

I assume that multer calls the functions provided repeatedly, which is why you don't do the obvious thing Jim Nilsson suggested. Also, sadly, you've said that the file you receive in the transform callback doesn't have the name you specify earlier.

Two possibilities, both assuming that either the file object or the req object you receive is the same in both callbacks:

  1. Your own expando property
  2. A WeakMap

Expando property

You could try to piggyback it on the file/req (I use file below), like so (see *** comments):

const singleImageUploadJpg = multer({
  storage: multerS3({
    s3: s3,
    bucket: "muh-bucket",
    acl: "public-read",
    key: function(req, file, cb) {
      file.__uuid__ = uuid.v4();                   // ***
      cb(null, file.__uuid__);
    },
    shouldTransform: function(req, file, cb) {
      cb(null, true);
    },
    transforms: [
      {
        id: "original",
        key: function(req, file, cb) {
          cb(null, `${uuid.v4()}.jpg`);
        },
        transform: function(req, file, cb) {
          cb(
            null,
            sharp()
              .resize()
              .jpeg({ quality: 50 })
          );
        }
      },
      {
        id: "small",
        key: function(req, file, cb) {
          cb(null, `${file.__uuid__}_small.jpg`);  // ***
        },
        transform: function(req, file, cb) {
          cb(
            null,
            sharp()
              .resize()
              .jpeg({ quality: 50 })
          );
        }
      }
    ]
  }),
  limits: { fileSize: 50 * 1024 * 1024 }
}).single("image");

That would probably be doing something undocumented, though, which means you need to be careful to test with every "dot release" of the library you upgrade to.

WeakMap:

Alternatively, you could use a WeakMap keyed by the file or req (I use file below):

const nameMap = new WeakMap();
const singleImageUploadJpg = multer({
  storage: multerS3({
    s3: s3,
    bucket: "muh-bucket",
    acl: "public-read",
    key: function(req, file, cb) {
      const fileName = uuid.v4();
      nameMap.set(file, fileName);                  // ***
      cb(null, fileName);
    },
    shouldTransform: function(req, file, cb) {
      cb(null, true);
    },
    transforms: [
      {
        id: "original",
        key: function(req, file, cb) {
          cb(null, `${uuid.v4()}.jpg`);
        },
        transform: function(req, file, cb) {
          cb(
            null,
            sharp()
              .resize()
              .jpeg({ quality: 50 })
          );
        }
      },
      {
        id: "small",
        key: function(req, file, cb) {
          const fileName = nameMap.get(file); // ***
          nameMap.delete(file);               // *** (optional, presumably `file` will be released at some point, which would remove it automatically)
          cb(null, `${fileName}_small.jpg`);  // ***
        },
        transform: function(req, file, cb) {
          cb(
            null,
            sharp()
              .resize()
              .jpeg({ quality: 50 })
          );
        }
      }
    ]
  }),
  limits: { fileSize: 50 * 1024 * 1024 }
}).single("image");

Tags:

Javascript