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:
- Your own expando property
- 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");