mp4 file upload issue in multer of node.js - node.js

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');

Related

Uploading file using multer triggers process.on('SIGINT')

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 })
});

Multer is not processing file upload in typescript-node.js

import multer, { FileFilterCallback } from "multer";
import { Request } from "express";
import { randomBytes } from "crypto";
const fileStorage = multer.diskStorage({
destination: (req: Request, file: Express.Multer.File, cb) => {
// if I add absolute path for "images", it would be stored in db as absolute, so when I retrieve the path for the <img src=""/> src would not accept because it requires "/images/
cb(null, "images");
},
filename: (req, file, cb) => {
cb(null, randomBytes(4).toString("hex") + "-" + file.originalname);
},
});
const fileFilter = (
req: Request,
file: Express.Multer.File,
cb: FileFilterCallback
) => {
if (
file.mimetype === "image/png" ||
file.mimetype === "image/jpg" ||
file.mimetype === "image/jpeg"
) {
cb(null, true);
} else {
cb(null, false);
}
};
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ storage: fileStorage, fileFilter }).single("image"))
Same code was working for js but when I converted to Typescript, it breaks. when I submit the form, it is spinning, means multer is not passing it to next middleware.
When I pass absolute path it works, but the issue with absolute path, it will save the absolute path to the database and when I retrieve it <img src="/home/..."> absolute path will be returned and it won't display the image:
const mainFile = path.dirname(process!.mainModule!.filename);
const imagesPath = path.join(mainFile, "images");
const fileStorage = multer.diskStorage({
destination: (req: Request, file: Express.Multer.File, cb) => {
cb(null, imagesPath);
},
filename: (req, file, cb) => {
cb(null, randomBytes(4).toString("hex") + "-" + file.originalname);
},
});
I edited ts.config.json but still get that error:
"baseUrl": "./src"

Multer upload an image to node js server (Github as storage)

I deployed a web based application but the multer upload doesn't work. It does work in localhost there is no error but the file/s are not save in my director. Here is my code:
const multer = require("multer");
const imageFilter = (req, file, cb) => {
if (file.mimetype.startsWith("image")) {
cb(null, true);
} else {
cb("Please upload only images.", false);
}
};
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, __basedir + "/resources/static/assets/uploads/");
},
filename: (req, file, cb) => {
cb(null, `${file.originalname}`);
},
});
var uploadFile = multer({ storage: storage, fileFilter: imageFilter });
module.exports = uploadFile;
What happen is the __basedir expression will cause "Uncaught ReferenceError: __basedir is not defined" error, but it's silently eaten in the code. To get the error to properly propagate, try adding try-catch block around the offending line this:
const storage = multer.diskStorage({
destination: (req, file, cb) => {
try {
cb(null, __basedir + "/resources/static/assets/uploads/");
} catch (e) {
cb(e);
}
},
filename: (req, file, cb) => {
cb(null, `${file.originalname}`);
}
});

How can i use multer with react?

I am build a web app with Node.js and React and I am trying to store some files at my backend.
For some reason i cant access to my req.path , although I configured all multer strategies.
const multer = require('multer')
const config = require('config')
const auth = require('../../middleware/auth')
const {check , validationResult } = require('express-validator');
const storage = multer.diskStorage({
destination: function(req, file , cb){
cb(null,'uploads/')
},
filename: function(req, file, cb){
cb(null, req.user.id)
}
});
const fileFilter = (req, file , cb) =>{
if(file.mimetype === 'image/jpeg' || file.mimetype === 'image/jpg' || file.mimetype === 'image/png')
cb(null,false);
else
cb(null,true);
}
my route:
router.post('/' , [auth,upload.single('image'),
[
check('status','Status is required').not().isEmpty(),
check('skills','Skills is required').not().isEmpty(),
check('gender','Gender is required').not().isEmpty()
]],
async (req,res) => {// cant access to req.file.....}
and my react form:
<div className="form-group">
<input type="text" placeholder="Choose profile image" name="profileImage" value={image}/>
<input type="file" placeholder="Upload" enctype="multipart/form-data" name="image" onChange={(e) => onChange(e)}/>
<small className="form-text">The image must not be bigger then 5MB and only JPG\JPEG\PNG types</small>
</div>
Please , what am i doing wrong?
I have used multer in my backend application and this is how I have configured it and it works properly and stores required files in server file directory.
First, installing multer
npm i multer --save
Second, initialize it at the top of required .js file
const multer = require("multer");
Now, configuring storage (storage location and filename)
const storage = multer.diskStorage({
destination: "./public/uploads/postimages/",
filename: function (req, file, cb) {
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
Init multer function, (configure own file size)
Use array if you want to upload multiple files at once, 10 is the number of files, you can modify it as needed.
const upload = multer({
storage: storage,
limits: { fileSize: 10000000000 },
}).array("image", 10);
// Use .single("image"); if you want to upload a single file.
// image is the name/key that is sent from frontend with the file(s).
If you are using array, you can create an api that stores file, which will look like this.
try {
let imagePath = "abc";
let postId = req.params.postId;
let imagesLinks = [];
await upload(req, res, (err) => {
if (err) {
console.log(err);
} else {
if (req.files == undefined) {
console.log("File not found.");
} else {
//image uploaded successfully
req.files.map(function (file) {
imagePath = "uploads/postimages/" + file.filename;
imagesLinks.push(tmp);
});
}
}
res.status(201).send(imagesLinks);
});
}
For a single file, it looks as simple as this
try {
let imagePath = "abc";
upload(req, res, (err) => {
if (err) {
res.status(300).send(err);
console.log(err);
} else {
if (req.file == undefined) {
res.status(301).send("image upload failed.");
} else {
//image uploaded successfully
imagePath = "uploads/" + req.file.filename;
storeImageLink(res, imagePath);
}
}
});
}
Look at these examples. They will be help you:
File Upload With Multer in Node.js and Express
Multer Storage:
// SET STORAGE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
Handling File Uploads:
app.post('/uploadfile', upload.single('myFile'), (req, res, next) => {
const file = req.file
if (!file) {
const error = new Error('Please upload a file')
error.httpStatusCode = 400
return next(error)
}
res.send(file)
})
Reactjs nodejs upload image — How to upload image using reactjs and nodejs (multer)
Node.js:
const path = require("path");
const multer = require("multer");
const storage = multer.diskStorage({
destination: "./public/uploads/",
filename: function(req, file, cb){
cb(null,"IMAGE-" + Date.now() + path.extname(file.originalname));
}
});
const upload = multer({
storage: storage,
limits:{fileSize: 1000000},
}).single("myImage");
const router = express.Router();
router.post("/upload", {
upload(req, res, (err) => {
console.log("Request ---", req.body);
console.log("Request file ---", req.file);//Here you get file.
/*Now do where ever you want to do*/
if(!err)
return res.send(200).end();
});
};);

Multer fileFilter is not getting called and req.body is empty

for some reason the fileFilter on multer is not getting called.
here is my Controller (i am using express routers)
const express = require('express');
const router = express.Router();
const UploadController = require('../controllers/UploadController');
router.route('/upload').post(UploadController.upload);
module.exports = router;
and this is the controller
const multer = require('multer');
const fs = require('fs');
module.exports = {
upload: function (req, res) {
let storage = multer.diskStorage({
destination: function (req, file, cb) {
console.log('here');
const filesDir = './uploads/' + req.body.ref;
if (!fs.existsSync(filesDir)) {
fs.mkdirSync(filesDir);
}
cb(null, filesDir);
},
filename: function (req, file, cb) {
let extArray = file.mimetype.split("/");
let extension = extArray[extArray.length - 1];
cb(null, req.body.type + '-' + Date.now() + '.' + extension);
},
fileFilter : function (req, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
}
})
const upload = multer({ storage: storage }).single('file');
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
res.send({
error: err
});
} else if (err) {
res.send({
error: err
});
}else{
res.send({
file: req.file,
body: req.body
});
}
});
}
}
I have following issues:
The fileFilter function is not even called so its not validating files
the req.body on the upload function (upload: function (req, res)) is empty it is only available in diskStorage and last upload function (upload(req, res, function (err)) so i cannot validate the body data also.
I had the same problem. the fileFilter function has to be defined inside multer, not inside the diskStorage function.
To make it a bit more readable I defined the storage and filter in variables instead of making everything inside the multer call.
// storage settings
const multerStorage = multer.diskStorage({
destination: function(req, file, next) {
next(null, './public/files');
},
filename: function(req, file, next) {
const sanitizedName = file.originalname
.replace('/[^a-z0-9\./gi', '-')
.replace('/-{2,}/g', '-')
.toLowerCase();
const name = Date.now() + '-' + sanitizedName;
// sending the file name to be stored in the database
req.body.filename = name;
next(null, name);
},
limits: {
fileSize: 25000000
}
});
// filter function
const multerFilter = function(req, file, cb) {
const ext = path.extname(file.originalname).toLowerCase();
if (ext !== '.pdf') {
cb(new Error('File must be in PDF format.'));
}
cb(null, true);
}
And then applying the storage settings and filter function to multer:
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter
});

Resources