I am working on a mod site, and I was able to create a method that uploads an image, but I was wondering if it's possible to also upload a zip file in the same method. I tried chaining on code for the file after creating a file model, but I get an unexpected field error. Here's the method I'm trying
router.post('/upload', uploadImage.single('image'), uploadFile.single('file'), IsLoggedIn, (req, res, next) => {
console.log(req.file);
var newImg = new Image({
data: req.file.filename
});
var newFile = new File({
data: req.file.filename
});
Mod.create({
name: req.body.name,
image: newImg.data,
game: req.body.game,
file: newFile.data
}, (err, newMod) => {
if (err) {
console.log(err);
}
else {
res.redirect('/mods');
}
});
});
And here are my storage engines
const imageStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './public/images')
},
filename: (req, file, cb) => {
cb(null, file.originalname)
}
});
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './public/images')
},
filename: (req, file, cb) => {
cb(null, file.originalname)
}
});
const uploadImage = multer({storage: imageStorage});
const uploadFile = multer({storage: fileStorage});
Is it possible to use 2 storage engines and chain 2 uploads in one method, or am I going about it all wrong? Any clarification or direction would be greatly appreciated.
Related
First of all I'm working with Node.JS with Express
I made a code that allows me to upload an image with multer to a specific directory, and here is a simplified version of it:
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'images')
},
filename: (req, file, cb) => {
cb(null, "some_random_name.jpg")
},
})
const upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (path.extname(file.originalname) != '.jpg')
return cb("Invalid file type, try uploading a '.jpg' file")
else
cb(null, true)
}
}).single('image')
router.post('/', (req, res) => {
upload(req, res, (err) => {
if (err)
return res.status(400).send({ error: err.message })
else
dbController.query(/* INSERT INTO images ... */)
}
)
})
The code works perfectly, but when I give a non existing file to it, it creates a file as if the file existed.
So to solve this I have to make sure that the file really exists before uploading it.
How can I implement this.
I feel like my code is complete frankenstein at this point but I do wonder why this formula does not work.
Once the file is uploaded, I can access the path with req.file.path and so I try to plug that into sharp but nothing happens. I'm not getting any errors or the expected result. (I'm using .rotate() to make it more obvious in testing)
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'public/uploads')
},
filename: function(req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
});
var upload = multer({
storage: storage
});
router.post("/new", upload.single('image'), function(req, res) {
sharp(req.file.path).rotate();
var post = {
title: req.body.title,
image: uploadedImage,
description: req.body.description,
body: req.body.body
}
Blog.create(post, function(err, newPost) {
if (err) {
console.log(err);
res.redirect("/")
} else {
res.redirect("/");
}
});
});
You either need to use async/await or Promises as the calls to sharp are asynchronous. You will also need to do something with the modified/rotated file like copying it to a Buffer or saving to a File. See these examples in the documentation.
// use an async function
router.post("/new", upload.single('image'), async function(req, res) {
await sharp(req.file.path).rotate().toFile('/path/to/file');
// ... rest of your code
});
I am trying to upload an image using multer but the images gets saved as an Id .
I have tried to set the file name to original name still the name of file doesn't change
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads')
}},{
filename: function (req, file, cb) {
cb(null, file.originalname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
let PhotoModel = require('../models/photo')
router.post('/',upload.single('image'),(req, res, next) => {
let msg = new PhotoModel(
{images: req.file.originalname}
)
msg.save()
.then(doc => {
console.log(doc)
})
.catch(err => {
console.error(err)
})
res.send(msg)
})
I am uploading the images using multer. They all are given random names (dec93b9f333c7a731723b06ce73c0bbc.jpg), which is very bad for SEO... Can you guys help me out, how to save the images with the pattern: 'fixed-name'+'random-name'.extension. Then at least part of the file would be readable for the google. Thanks!
app.set('images', '/var/www/images');
app.use(app.get('images'), express.static(app.get('images')));
var multerForImage = multer({
dest: app.get('images'),
onParseStart: function (file) {
console.log("Started parsing file stream", file);
},
onFileUploadStart: function (file) {
console.log('File recieved: ', file.originalname);
},
onFileUploadComplete: function (file, req, res) {
console.log("File upload complete");
var path = app.get('images') + "/" + file.name;
var user = req.session.user;
res.json({
success: true,
data: path
});
},
onFileUploadData: function (file, data, req, res) {
console.log('Data recieved for file upload');
},
onParseEnd: function (req, next) {
console.log("Parsing data end for file upload");
}
});
You can use the storage configuration.
app.set('images', '/var/www/images');
app.use(app.get('images'), express.static(app.get('images')));
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, app.get('images'))
},
filename: function (req, file, cb) {
const randomPart = uuidV4(); // use whatever random you want.
const extension = file.mimetype.split('/')[1];
cb(null, 'fixed-name'+ randomPart + `.${extension}`)
}
})
var multerForImage = multer({
storage: storage,
...
I am building a webapplication that allows users to upload an avatar. However, in addition to the avatar I want to create a thumbnail low-res (e.g. 64 x 64) and store it on my server. Currently I'm using this code to store the image in two directories, but it's the same resolution in both directories. How would I store a different resolution in the thumbnails directory?
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/thumbs');
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
You can use sharp for resize you images in your router:
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './uploads')
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
and:
router.post('/', upload.single('image'), async (req, res) => {
try {
const { filename: image } = req.file
await sharp(req.file.path, { failOnError: false })
.resize(64, 64)
.withMetadata()
.toFile(
path.resolve(req.file.destination, './thumbs', image.replace(/\.(jpeg|png)$/, `.jpg`))
)
fs.unlink(req.file.path)
return res.json({
thumb_url: '/uploads/thumbs/' + image.replace(/\.(jpeg|png)$/, `.jpg`)
});
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error!');
}
});
fs.unlink(req.file.path) remove your orginal image from ./uploads