I implemented the server to receive file using the lib multer, it works for photographs(PNG, JPEG) but not for PDF ... acctually i can receive but the file got corrupted. If someone could help me i appreciate :)
Multer´s config :
import crypto from 'crypto';
import multer from 'multer';
import { extname, resolve } from 'path';
export default {
storage: multer.diskStorage({
destination: resolve(__dirname, '..', '..', 'tmp', 'uploads'),
filename: (req, file, cb) => {
crypto.randomBytes(16, (err, raw) => {
if (err) return cb(err);
return cb(null, raw.toString('hex') + extname(file.originalname));
});
},
}),
};
Middleware :
middlewares() {
this.server.use(cors());
this.server.use(express.json());
this.server.use(
'/files',
express.static(resolve(__dirname, '..', '..', 'tmp', 'uploads'))
);
}
Routes:
const routes = new Router();
const upload = multer(multerConfig);
routes.post('/files', upload.single('file'), FileController.store);
FileController:
import File from '../models/File';
class FileController {
async index(req, res) {
const file = await File.findByPk(req.params.id);
res.json(file);
}
async store(req, res) {
const { originalname: name, filename: path } = req.file;
const file = await File.create({
name,
path,
});
return res.json(file);
}
}
export default new FileController();
Related
When I upload file using multer nodemon restarts web server. It's fine on my local machine which is windows. It only happens when I start my server on ubuntu machine. What's the problem? My code is here below.
const path = require("path");
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '../public/uploads/'))
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
});
function checkFileType(file, cb) {
const filetypes = /jpeg|jpg|png|gif/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
} else {
cb('Only images! jpeg|jpg|png|gif ');
}
}
const upload = multer({
storage: storage,
limits: { fileSize: 5242880 },
fileFilter: function (_req, file, cb) {
checkFileType(file, cb);
}
});
router.route('/upload').post(protect, upload.array('banner', 12), (req, res, next) => {
console.log(req.files)
if (!req.files) {
res.status(400).json({ success: false, message: 'File not found' });
return;
}
const data = [];
const baseUrl = `THE_URL_FILE_UPLOAD`;
req.files.map((file, idx) => {
data.push({ path: baseUrl + file.originalname })
})
res.status(200).json({ success: true, data })
});
i have a user.js in model folder
const UserSchema = new mongoose.Schema({
name: {
type: String,
},
profile_pic: {
data: Buffer,
contentType: String
}
})
i want to upload a profile picture
and in the router folder i defined the storage using multer
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, './images')
},
filename: (req, file, callback) => {
callback(null , Date.now()+ file.originalname)
}
})
const upload = multer({
storage : storage,
limits : {
fieldSize : 1024*1024*3
}
})
router.post('/image' , upload.single('image'),image)
using postman i tried to upload an image .. it uploaded successfully and stored in the defined folder (images)
but i want to store the image in the model too
how to store it in the controller folder user.js
Try the example below
const app = require("express")();
const multer = require('multer')
const firstLocation = multer.diskStorage({
destination: function (req, file, cb) {');
cb(null, './imagesFolder/')
},
filename: (req, file, callback) => {
callback(null , Date.now()+ file.originalname)
}
});
const secondLocation = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './modelFolder/')
},
filename: (req, file, callback) => {
callback(null , Date.now()+ file.originalname)
}
});
const firstPath = multer({ storage: firstLocation })
const secondPath = multer({ storage: secondLocation })
function fileUpload(req, res, next) {
firstPath.single('file')(req, res, next);
secondPath.single('file')(req, res, next);
next();
}
app.post("/", fileUpload, (req, res) => {
res.send("Received file");
});
app.listen(3000, () => {
console.log("Server started");
});
If you run the above code and send a request to localhost:3000 then you will notice that two directories created named imagesFolder and modelFolder. Inside those folders, you will see the file that you have uploaded.
Updated answer in response to comments for Mongo schema,
const imagePath = '/path/to/myImage.jpg';
const imageUp = mongoose.model('imageUp', UserSchema);
mongoose.connection.on('open', function () {
imageUp.remove((err) => {
if (err) throw err;
const up = new imageUp;
up.img.data = fs.readFileSync(imagePath); // read from you folder
up.img.contentType = 'image/jpg'; // set the content tpe to image format
up.save((err, a) => { // save or upload image
if (err) throw err; // throws error if anything goes wrong
app.get('/', (req, res, next) => {
imageUp.findById(up, (err, doc) => { // fetch image from db by id and send in response as required.
if (err) return next(err);
res.contentType(doc.img.contentType);
res.send(doc.img.data);
});
});
}
Ref:- https://www.geeksforgeeks.org/upload-and-retrieve-image-on-mongodb-using-mongoose/
I am using cloudinary with node and multer
I successfully managed to store images but i noticed each time i upload an image it creates two copies : one with the public_id as a name (in the assets) and the other with the original name(in 'profiles' folder).
I want to delete both whenever i upload a new image but it only deletes the one in the assets and don't delete the one in the 'profiles' picture.
My upload route looks like this
import path from "path";
import express from "express";
import dotenv from "dotenv";
import cloudinary from "cloudinary";
import { CloudinaryStorage } from "multer-storage-cloudinary";
import multer from "multer";
dotenv.config();
const cloud = cloudinary.v2;
const router = express.Router();
cloud.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const storage = new CloudinaryStorage({
cloudinary: cloud,
params: {
folder: "profiles",
transformation: { gravity: "center", height: 300, width: 300, crop: "fill" },
public_id: (req, file) =>
`${file.originalname.split(".")[0]}-${Date.now()}`,
},
});
function checkFileType(file, cb) {
const filetypes = /jpg|jpeg|png/;
const extname = filetypes.test(
path.extname(file.originalname).toLocaleLowerCase()
);
const mimetype = filetypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
cb(null, false);
}
}
const upload = multer({
storage,
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
});
router.post("/", upload.single("image"), async (req, res) => {
try {
const result = await cloud.uploader.upload(req.file.path)
res.send(result);
} catch(error) {
console.log(error)
}
});
export default router;
And the delete route
import express from "express";
import dotenv from "dotenv";
import cloudinary from "cloudinary";
dotenv.config();
const cloud = cloudinary.v2;
const router = express.Router();
cloud.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
router.post('/:id', async (req, res) =>{
try {
await cloud.uploader.destroy(req.params.id);
// await cloud.uploader.destroy(`/profiles/${req.params.id}`);
res.send(result);
} catch (err) {
return res.status(500).json({msg: err.message})
}
})
export default router;
Can anyone help ?
In case anyone face the same issue
I was sending the image twice in the upload route
Just change it to this
router.post("/", upload.single("image"), async (req, res) => {
try {
res.json(req.file);
} catch (error) {
console.log(error);
}
});
I'm trying to upload mp4 file by using multer in node.js
(View)VideoUploadPage.js
import React, { useState } from "react";
import Axios from "axios";
function VideoUploadPage() {
const onDrop = (files) => {
let formData = new FormData();
const config = {
header: { "content-type": "multipart/form-data" },
};
formData.append("file", files[0]);
console.log(files);
Axios.post("/api/video/uploadfiles", formData, config).then((response) => {
if (response.data.success) {
console.log(response.data);
} else {
alert("비디오 업로드를 실패 했습니다.");
}
});
};
}
(Server)
video.js
const express = require("express");
const router = express.Router();
const multer = require("multer");
const path = require("path");
const ffmpeg = require("fluent-ffmpeg");
let storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads/");
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}_${file.originalname}`);
},
fileFilter: (req, file, cb) => {
const ext = path.extname(file.originalname);
if (ext !== ".mp4") {
return cb(res.status(400).end("only mp4 is allowed"), false);
}
cb(null, true);
},
});
const upload = multer({ storage: storage }).single("file");
router.post("/uploadfiles", (req, res) => {
upload(req, res, (err) => {
if (err) {
return res.json({ success: false, err });
}
return res.json({
success: true,
url: res.req.file.path,
fileName: res.req.file.filename,
});
});
});
At the video.js destination: (req, file, cb) => {
cb(null, "uploads/")
} <----- I can check which file is going to upload with console.log(response.data), but there is no mp4 file in the "uploads" folder.
When I changed "uploads/" to my local directory path, mp4 file is on the uploads folder ....
ex: "C://~~~/uploads"
Any idea?
use path.resolve('./uploads') to resolve a sequence of path-segments to an absolute path.
let storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.resolve('./uploads'); // path of the upload folder
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}_${file.originalname}`);
},
fileFilter: (req, file, cb) => {
const ext = path.extname(file.originalname);
if (ext !== ".mp4") {
return cb(res.status(400).end("only mp4 is allowed"), false);
}
cb(null, true);
},
});
You can use path.resolve(process.cwd() + 'path till upload folder');
for eg:
path.resolve(process.cwd() + '/uploads');
I am trying to upload images in an express server using multer, however, uploading images using postman using the route below, gives the json message { msg: 'image uploaded successfully' } (i.e., the route is reached correctly), but req.file gives undefined. Why? the related file structure is as follows, to make sure I am referencing the destination correctly:
-backend
--routes
---uploadRoutes.js
--server.js
-frontend
-uploads
uploadRoutes.js
import path from 'path';
import express from 'express';
import multer from 'multer';
const router = express.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)}`
);
},
});
function checkFileType(file, cb) {
const filetypes = /jpg|jpeg|png/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
cb('Images only!');
}
}
const upload = multer({
storage,
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
});
router.post('/', upload.single('image'), (req, res) => {
console.log(req.file);
try {
res.status(200).json({ msg: 'image uploaded successfully' });
} catch (error) {
console.error(error.message);
}
// res.send(`/${req.file.path}`);
});
export default router;
just check the header and body form-data request, because your code is correctly if you have this line in the app file
app.use("/uploads", express.static("uploads"));
header of request