I'm trying to make a file upload API using multer gridFS, I used the documentation but I'm missing something:
this is my code:
const config = require("config");
const express = require("express");
const router = express.Router();
const dbURI = config.get("mongoURI");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const GridFsStorage = require("multer-gridfs-storage");
var storage = new GridFsStorage({
url: dbURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads"
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
router.post("/upload", upload.single("file"), (req, res) => {
res.json({ msg: "file uploaded successfully" });
});
I get an error TypeError: Router.use() requires a middleware function but got a Object which basically tells me that upload.single is not a function, what is my error?
I found the mistake, I was missing module.exports = router;
Related
I want to resize and compress images using sharp library in node.js. The code was taken from this article, but for some reason returns an error.
Error
PS D:\Code\Web\image-compressor-nodejs> node index.js
[Error: ./uploads/2022-08-10T18:35:49.251Z-2021-11-18_23.44.45.png.webp: unable to open for write
windows error: ���������� �� �������� �������.
]
Code
const express = require("express");
const multer = require("multer");
const sharp = require("sharp");
const fs = require("fs");
const app = express();
const storage = multer.memoryStorage();
const upload = multer({ storage });
app.use(express.static("./uploads"));
app.post("/", upload.single("picture"), async (req, res) => {
try {
fs.access("./uploads", (error) => {
if (error) {
fs.mkdirSync("./uploads");
}
});
const { buffer, originalname } = req.file;
const timestamp = new Date().toISOString();
const ref = `${timestamp}-${originalname}.webp`;
await sharp(buffer)
.webp({ quality: 20 })
.toFile("./uploads/" + ref);
const link = `http://localhost:3000/${ref}`;
return res.json({ link });
} catch (error) {
console.log(error);
}
});
app.listen(3000);
I am trying to upload, save and display images in MongoDB using express server and GridFS.
Data is sent with FormData with vue.js on the front-end and that part works well.
Images are getting to the server, and it stores that data, but I can not display the uploaded image, instead I get this
It displays the Image in some encoding I guess.
Here is server code for receiving, storing and displaying images.
const express = require('express')
const mongodb = require('mongodb')
const path = require('path')
const crypto = require('crypto')
const mongoose = require('mongoose')
const multer = require('multer')
const GridFsStorage = require('multer-gridfs-storage')
const Grid = require('gridfs-stream')
const methodOverride = require('method-override')
const config = require('../../config/keys')
const morgan = require('morgan')
const images = express()
// MIDDLEWARE
images.use(methodOverride('_method'))
// images.use(morgan("default"))
// MONGO URI
const mongoURI = config.dbUrl
// CREATE MONGO CONNECTION
const conn = mongoose.createConnection(mongoURI)
// INITALIZE GRID FS
let gfs
conn.once('open', () => {
gfs = Grid(conn.db, mongoose.mongo)
gfs.collection('uploads')
})
// CREATING STORAGE ENGINE
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
const filename = file.originalname
const fileInfo = {
filename,
bucketName: 'uploads'
}
resolve(fileInfo)
})
}
})
const upload = multer({ storage })
// POST REQUEST UPLOADS FILE TO DATABASE
images.post('/', upload.single('image'), (req, res) => {
console.log('POST REQUEST TO HTTP://LOCALHOST:3000/API/BACKEND/IMAGES/')
res.json(req.file)
console.log(req.file)
})
// GET REQUEST
images.get('/', async (req, res) => {
console.log('GET REQUEST TO HTTP://LOCALHOST:3000/API/BACKEND/IMAGES/')
const posts = await load();
res.send(await posts.find({}).toArray())
})
images.get('/:filename', (req, res) => {
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
// Check if file
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// Check if image
if (file.contentType === 'image/jpeg' || file.contentType === 'image/png') {
// Read output to browser
const readstream = gfs.createReadStream(file.filename);
readstream.pipe(res);
} else {
res.status(404).json({
err: 'Not an image'
});
}
});
});
// LOADING FUNCTION FOR MONGODB
async function load() {
const client = await mongodb.MongoClient.connect
(`${config.dbUrl}`, {
useNewUrlParser: true,
useUnifiedTopology: true
});
return client.db('myCluster').collection('uploads.files');
}
module.exports = images
Every help would be nice and much appreciated! Thanks! :)
Instead of storing file directly into mongodb I want to store using mongoose library. How to use mongoose library using the code frame same?
Update:: Saved in mongoose library. Now it uploads all of the file but how can I just store only the docx file instead of image file. And uploading anyother file should say invalid file.
update 2:: Resolved with the issue. Now capable of only allowing docxx file. Now need to add filename with extention as mentioned in the comment section. How to use that part of code.
Middleware::upload.js
const util = require("util");
const multer = require("multer");
const GridFsStorage = require("multer-gridfs-storage");
const mongoose = require('mongoose');
const Grid = require('gridfs-stream');
const mongoURI ='mongodb://localhost:27017/file_uploaded';
const promise = mongoose.connect(mongoURI, { useNewUrlParser: true });
const conn = mongoose.connection;
let gfs;
conn.once('open',() => {
gfs = Grid(conn, mongoose.mongo);
gfs.collection('uploads');
});
var storage = new GridFsStorage({
db: promise,
options: { useNewUrlParser: true, useUnifiedTopology: true },
file: (req, file) => {
return new Promise((resolve, reject) => {
if (file.mimetype === 'application/vnd.openxmlformats-
officedocument.wordprocessingml.document') {
resolve({
bucketName: 'words'
})
***//Add filename inorder to maintain original final name with
extention***
//const filename = `${Date.now()}-
bezkoder-${file.originalname}`;
//return filename;
} else {
reject(Error("File type has been rejected"));
}
});
}
});
var uploadFile = multer({ storage: storage }).single("file");
var uploadFilesMiddleware = util.promisify(uploadFile);
module.exports = uploadFilesMiddleware;
You dont need to use GridFsStorage. Try below code.
// file-controller.js
const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const router = express.Router();
const multerStorage = multer.memoryStorage();
const upload = multer({ storage: multerStorage, });
const imageSchema = mongoose.Schema({
image: { data: Buffer, contentType: String },
}, { timestamps: true });
const ImageModel = mongoose.model('images', imageSchema);
router.post('/upload', upload.single('image'), async (req, res, next) => {
const image = { data: new Buffer.from(req.file.buffer, 'base64'), contentType: req.file.mimetype }
const savedImage = await ImageModel.create(image);
res.send(savedImage);
});
router.get('/getImage/:id', async (req, res, next) => {
const { id: _id } = req.params;
// If you dont use lean(), you wont decode image as base64
const image = await ImageModel.findOne({ _id }).lean().exec();
res.send(image);
});
module.exports = router;
Serve route via express.
const express = require('express');
const FileController = require('./file-controller');
const app = express();
// Mongo DB connection code ...
// Serve static files code ...
app.use('/file', FileController);
app.listen(3000, () => console.log(`Example app listening on port ${port}!`));
I have a problem uploading image file to my mongoDB using gridFS, but for some reason this doesn't work
this is my code :
const config = require("config");
const express = require("express");
const router = express.Router();
const dbURI = config.get("mongoURI");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const GridFsStorage = require("multer-gridfs-storage");
var storageImage = new GridFsStorage({
url: dbURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "user_images"
};
resolve(fileInfo);
});
});
}
});
const uploadImage = multer({ storageImage });
router.post("/uploadImage", uploadImage.single("userImg"), (req, res) => {
console.log("uploading");
console.log(req.file);
res.json({ msg: "file uploaded successfully" });
});
module.exports = router;
when I console .log req.file I get undefined, does anyone know what the problem is?
I found the problem:
const uploadImage = multer({ storageImage });
it should be
const uploadImage= multer({storage:storageImage});
This is my current code. It does not work.
I post the image in form data.
My Questions are:
How can i see the form data in node.js (try log req.body and it is an empty object)
What does the "demo.jpg" in the code mean?
NODEJS
var aws = require('aws-sdk');
const express = require('express');
const router = express.Router();
aws.config.update({
"accessKeyId": "<MY_KEY>",
"secretAccessKey": "<MY_SECRET>"
});
router.post('/', (req, res, next) => {
console.log(res.body)
var s3 = new aws.S3();
var params = {
Bucket: "passwordapp",
Key: 'aaaaaa',
Expires: 60,
ContentType: 'jpg'
};
s3.getSignedUrl('demo.jpg', params, function(err, data) {
//console.log("err",err);
if (err) {
res.json(err)
} else {
res.json(data)
}
});
});
module.exports = router;
Ok got the solution from here:
https://stackoverflow.com/a/54402849/1230198
use multer
this is my WORKING code:
const express = require('express');
const router = express.Router();
const AWS = require('aws-sdk');
const multer = require('multer');
const storage = multer.memoryStorage()
const upload = multer({storage: storage});
const s3Client = new AWS.S3({
"accessKeyId": "<KEY>",
"secretAccessKey": "<SECRET>"
});
const uploadParams = {
Bucket: 'passwordapp',
Key: '', // pass key
Body: null, // pass file body
};
router.post('/', upload.single("image"),(req, res, next) => {
const params = uploadParams;
uploadParams.Key = req.file.originalname;
uploadParams.Body = req.file.buffer;
s3Client.upload(params, (err, data) => {
if (err) {
res.status(500).json({error:"Error -> " + err});
}
res.json({message: 'File uploaded successfully','filename':
req.file.originalname, 'location': data.Location});
});
});
module.exports = router;