var express = require("express");
var multer = require('multer');
const exec = require('child_process').exec;
var app = express();
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(null, file.originalname);
}
});
var upload = multer({ storage : storage}).single('myfile');
debugger;
app.get('/',function(req,res){
res.sendFile(__dirname + "/index.html");
});
app.post('/uploadjavatpoint',function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
console.log("Uploading "+res.files);
res.end("File is uploaded successfully!");
console.log("Coverting to PDF");
debugger;
exec('"./px-8-5-4-win-x86-64/sdk/demo/pxsample.exe" "./uploads/EM_spectrum.ppt" "./uploads/EM_spectrum.pdf"');
console.log("Coversion Done");
});
});
app.listen(2000,function(){
console.log("Server is running on port 2000");
});
I am sending the file using postman with file(myfile) embedded in the body. I want to get the original name of the file being uploaded. I am new to node js please help me how to get the original name of the file being uploaded.
I tried req.file.filename as well as req.files but they don't seem to work
this should help you
> const _files = req.files;
> for (const file of _files) {
> name = file.originalname;
> size = file.size;
> }
in postman,
Choose form-data in the body, file in the key and select the file in the value
Related
I am trying to write an app using NodeJS and Express which will upload both a user avatar which is a single image (jpeg, png or webp) and 'legalDocs' which is essentially also a single file that can either be an image (jpeg, png or webp) or a pdf file. The avatar needs to be uploaded to ./resources/(userID)/userAvatar and the legal docs to ./resources/(userID)/legalDocs. Along with some other text info that will be posted along with the request as a multipart/form-data.
The userID is only generated after processing the text data posted.
Here's my current non-working code
APP.JS
//ENV
require("dotenv").config();
require("express-async-errors");
//EXPRESS
const express = require("express");
const server = express();
global.__basedir = __dirname;
//routes
const authRouter = require("./routes/authRoutes.js");
server.use(express.json());
server.use(express.urlencoded({extended: true}));
server.use(express.static("./public"));
server.use("/api/v0/auth", authRouter);
const port = process.env.PORT || 3000;
const start = async () => {
try {
server.listen(port, () => {
console.log(`--> Listening on port ${port}...`);
});
} catch (error) {
console.log(error);
console.log("Fatal error!");
}
}
start();
authRoutes.js:
const express = require("express");
const router = express.Router();
const {signupWithEmail} = require("../controllers/auth.js");
router.route("/signup").post(signupWithEmail);
module.exports = router;
../controllers/auth.js:
const multer = require("multer");
const processReq = require("../middleware/upload.js");
const signupWithEmail = async (req, res, next) => {
//Processing to get the ID happens here.
//For simplicity we can pretend like the ID is directly
//posted in a field with the name id.
const id = req.body.id;
console.log("id:");
console.log(id);
await processReq(id)(req, res, next);
res.status(200).send("done!");
}
upload.js
const multer = require("multer");
const errors = require("../errors");
const maxSize = 2 * 1024 * 1024;
const acceptableFileMIMETypes = ["image/jpeg", "image/png", "image/webp", "application/pdf"];
const userAvatarFilter = function (req, file, cb) {
if ((file.fieldname === "userAvatar" || file.fieldname === "legalDocs")
&& acceptableFileMIMETypes.includes(file.mimetype)
&& !(file.fieldname === "userAvatar" && file.mimetype === "application/pdf")) {
if (file.fieldname === "userAvatar") {
cb(null, true);
} else {
cb(null, false);
}
} else {
cb(new errors.BadRequestError("Both files are required, and must be JPEG, PNG, WEBP. Legal documents can also be PDF."));
}
}
const userlegalDocsFilter = function (req, file, cb) {
if ((file.fieldname === "userAvatar" || file.fieldname === "legalDocs")
&& acceptableFileMIMETypes.includes(file.mimetype)
&& !(file.fieldname === "userAvatar" && file.mimetype === "application/pdf")) {
if (file.fieldname === "userAvatar") {
cb(null, false);
} else {
cb(null, true);
}
} else {
cb(new errors.BadRequestError("Both files are required, and must be JPEG, PNG, WEBP. Legal documents can also be PDF."));
}
}
const uploadFunc = (id) => {
return (req, res, next) => {
const userAvatarStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, __basedir + `/resources/${id}/userAvatar`);
},
filename: (req, file, cb) => {
console.log("Uploaded avatar!");
console.log(file.originalname);
console.log(file);
cb(null, file.originalname);
}
});
const legalDocsStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, __basedir + `/resources/${id}/legalDocs`);
},
filename: (req, file, cb) => {
console.log("Uploaded legalDocs!");
console.log(file.originalname);
console.log(file);
cb(null, file.originalname);
}
});
const uploadAvatar = multer({
storage: userAvatarStorage,
limits: {
fileSize: maxSize,
files: 2
},
fileFilter: userAvatarFilter
}).any();
const uploadLegalDocs = multer({
storage: legalDocsStorage,
limits: {
fileSize: maxSize,
files: 2
},
fileFilter: userlegalDocsFilter
}).any();
uploadAvatar(req, res, next);
uploadLegalDocs(req, res, next);
next();
}
}
module.exports = uploadFunc;
The Problem
The first problem with my code is quite obvious, I cannot parse text data from the request unless it had been processed by multer (with the current code, console.logging the id shows that it's undefined), but I need the ID to be passed to multer in order to save the files to the correct directory. It seems like I need some way to process text only and generate the ID, then process the files.
The second problem is that, even if the ID is static - meaning that in ./controllers/auth.js the signupWithEmail function became:
const multer = require("multer");
const processReq = require("../middleware/upload.js");
const signupWithEmail = async (req, res, next) => {
const id = 1337;
console.log("id:");
console.log(id);
await processReq(id)(req, res, next);
res.status(200).send("done!");
}
I this is the output I get on the console when I try to post:
id:
1337
Uploaded legalDocs!
cours-analyse-numerique-ch1-21_22.pdf
{
fieldname: 'legalDocs',
originalname: 'cours-analyse-numerique-ch1-21_22.pdf',
encoding: '7bit',
mimetype: 'application/pdf'
}
node:_http_outgoing:771
throw new ERR_HTTP_HEADERS_SENT('remove');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot remove headers after they are sent to the client
at new NodeError (node:internal/errors:400:5)
at ServerResponse.removeHeader (node:_http_outgoing:771:11)
at write (C:\Users\der_u\source\repos\ATEEK\node_modules\finalhandler\index.js:282:9)
at AsyncResource.runInAsyncScope (node:async_hooks:204:9)
at listener (C:\Users\der_u\source\repos\ATEEK\node_modules\on-finished\index.js:170:15)
at onFinish (C:\Users\der_u\source\repos\ATEEK\node_modules\on-finished\index.js:101:5)
at callback (C:\Users\der_u\source\repos\ATEEK\node_modules\ee-first\index.js:55:10)
at IncomingMessage.onevent (C:\Users\der_u\source\repos\ATEEK\node_modules\ee-first\index.js:93:5)
at IncomingMessage.emit (node:events:513:28)
at endReadableNT (node:internal/streams/readable:1359:12) {
code: 'ERR_HTTP_HEADERS_SENT'
}
and only 'legalDocs' get uploaded.
Is there any way to solve these problems without using a temporary directory to save all the files then move them once the ID had been generated? And what does the [ERR_HTTP_HEADERS_SENT] error mean?
Multer does not save the file and I cannot see any logs... The folder is empty, no any files.
The image data is actually sent to the server as its console logged:
Screenshot of req.files from log
What am I doing wrong? Please help me find
const express = require('express');
const router = express.Router();
const path = require('path');
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log('destination') // can't see this log
cb(null, './uploads/');
},
filename: (req, file, cb) => {
console.log('filename') // can't see this log
const ext = file.mimetype.split("/")[1];
cb(null, Date.now() + path.extname(file.originalname));
}
});
const uploadImage = multer({
storage,
limits: { fieldSize: 1024 * 1024 },
fileFilter: (req, file, cb) => {
console.log('log!') // can't see this log
const ext = path.extname(file.originalname);
if (ext !== '.jpg' && ext !== '.jpeg' && ext !== '.png') {
console.log('not log!') // can't see this log
const err = new Error('Extention');
err.code = 'EXTENTION';
return cb(err);
}
console.log('log!') // can't see this log
cb(null, true);
}
}).single('photo');
router.post('/image', async (req, res) => {
console.log(req.files) // can see this log
uploadImage(req, res, err => {
console.log('upload') // can see this log
let error = '';
if (err) {
console.log(err)
if (err.code === 'LIMIT_FILE_SIZE') {
error = 'Max 500kb!';
}
if (err.code === 'EXTENTION') {
error = 'Only jpg and png!';
}
}
res.json({
ok: !error,
error
});
})
});
Multer finally gave an error, so the problem was resolved... The problem was that the names of these fields are different:
Server:
.single('pic');
And in the request to the server:
formData.append('pic', file);
The code seems to work fine for me but I just had to manually create the uploads directory.
I used postman to test this and the picture appeared in my uploads directory.
# Console Output
SERVER RUNNING ON 3000
undefined
log!
log!
destination
filename
upload
Have been trying to upload multiple images with multer array upload but they are not displaying in my index page but using single.upload() is working fine and displaying the images .
/ Set The Storage Engine
destination: './public/upload',
filename: function(req, file, cb){
cb(null,file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
// Init Upload
const upload = multer({
storage: storage,
limits:{
fileSize: 100000000
},
fileFilter: function(req, file, cb){
checkFileType(file, cb);
}
});
// Check File Type
function checkFileType(file, cb){
// Allowed ext
const filetypes = /jpeg|jpg|png|gif/;
// Check ext
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
// Check mime
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null,true);
} else {
cb('Error: Images Only!');
}
Var upload = multer({storage: storage})
router.post("/", upload.array('image'),(req, res) => {
const newSell= new Sell({
year: req.body.year,
text: req.body.text,
image:'/upload/'+req.files
});
newSell.save().then(sell => res.json(sell));
}
);
module.exports = router;
I am trying to upload a file image with multer in express and file is uploading in the directory, but name of the file is not saving in database. I am using mongodb with express. Filename is saving as noimage.png.
routes/posts.js:-
router.post('/add', function(req, res, next) {
if(req.files.mainimage){
console.log('Uploading files...');
// File Info
var mainImageOriginalName = req.files.mainimage.originalname;
var mainImageName = req.files.mainimage.name;
var mainImageMime = req.files.mainimage.mimetype;
var mainImagePath = req.files.mainimage.path;
var mainImageExt = req.files.mainimage.extension;
var mainImageSize = req.files.mainimage.size;
}
else{
var mainImageName = 'noimage.png';
}
//console.log(req.files.mainimage.name);
// Check for errors
var errors = req.validationErrors();
if(errors){
res.render('add', {
errors: errors,
});
}
else{
var posts = db.get('posts');
// Submit to db
posts.insert({
mainimage: mainImageName
}, function(err, post){
if(err){
res.send('There was an issue submitting the post');
}
else{
req.flash('success', 'Post Submitted');
res.location('/posts');
res.redirect('/posts');
}
});
}
});
If you are using multer it seems you didn't specify as multer's specification
router.post('/add', multer({ dest: './uploads/'}).single('myimage'), function(req,res){...})
I have some troubles using multer and promises (bluebird).
I try to upload a pdf file in a folder then extract the text inside this pdf with the plugin (textract)
Both of the functions I created works, but I have some trouble in the execution and the promisification of the upload function. here's my code :
pdf-rest.js :
var bodyParser = require('body-parser');
var request = require('request');
var jsonParser = bodyParser.json();
var fs = require('fs');
var Promise = require('bluebird');
var multer = require('multer');
var textract = require('textract');
module.exports = function(app) {
var destination = "uploads";
var filename = "" + Date.now() + ".pdf";
var filePath = "C:\\wamp64\\www\\ebook-stage\\backend\\rest\\uploads\\" + filename;
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, destination);
},
filename: function (req, file, cb) {
cb(null, filename);
}
});
app.post('/rest/create_pdf', function (req, res) {
var upload = multer({storage: storage}).single('file');
function uploadFile() {
var uploadFilePromise = new Promise(function (resolve, reject) {
upload(req, res, function (err) {
if (err) {
reject(err);
res.end('error uploading file')
}
else {
res.end('file uploaded');
console.log('fileupload')
}
});
resolve(upload);
});
console.log(uploadFilePromise);
return uploadFilePromise;
}
function textractPdf(path) {
textract.fromFileWithPath(path, function (error, text) {
console.log('textract');
if (text) {
console.log(text);
return text;
}
else {
console.log(error);
return error;
}
});
}
uploadFile().then(textractPdf(filePath));
});
server.js :
var express = require('express');
var app = express();
require('./pdf-rest.js')(app);
app.listen(8080);
I use a button to execute this script in a HTML page, the upload of the pdf in the folder work the first time I click on the button but the textract doesn't.
I know I do something wrong, the execution of the function textractPdf(Path) is done first. I think I didn't promisify correctly my upload function.