Formidable Not Uploading When Using Multer - javascript

I'm trying to create a page that lets you upload a file to a folder and say what a number is in an input. I'm new to the multer library(which is what I'm using right now) and I usually use body-parser. Here is my app.js and my upload.ejs, I'll explain what my problem is below it.
app.js
const express = require('express');
const http = require('http');
const formidable = require('formidable');
const fs = require('fs');
const ejs = require('ejs')
const path = require('path');
const multer = require('multer');
const upload = multer({ dest: 'upload/'});
const type = upload.any('gradeNumber');
const app = express();
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.get('/fileupload', function (req, res) {
res.render("upload")
});
app.post('/fileupload',type, function (req, res) {
const form = new formidable.IncomingForm();
console.log(req.body.gradeNumber);
form.parse(req, function (err, fields, files) {
const oldpath = files.filetoupload.path;
const newpath = 'C:/Users/Shubh Computer/Desktop/VSCode/Grades/1/' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
});
});
app.listen(3000);
upload.ejs
<!DOCTYPE html>
<html>
<head>
<title>Upload File</title>
</head>
<body>
<form action="fileupload" method="post" enctype="multipart/form-data">
<input type="file" name="filetoupload"><br>
<label>What Grade</label><input type="text" name="gradeNumber"><br>
<input type="submit">
</form>
</body>
</html>
Before I started to use multer, I was uploading the file to a specific folder without error, but would get the input value as undefined. After I added the app.post(/fileupload,type,function(req,res){}) I can log the input but can't upload the file(If I take out the type I can still upload the file). I was also wondering what the const upload = multer({ dest: 'upload/'}); does because I have a folder(not created by me) that holds weird files that Visual Studio can't support(Notepad can't support it either). I have a strong feeling it's something to do with that line, but like I said, I'm new to Multer. If somebody could come up with a solution that can upload and log the value that would be great!(I have spent a long time writing this I'm trying to get my reputation up so my votes can display to the public; I wouldn't mind if you can upvote my post!!)

Maybe start the URL with a / so that the intended URL is returned instead of its parent or child.
It might solve the folder issue.
and about the "type" middelware, I haven't seen yet any example of upload.any() with passing parameters.
I'm new to Multer too, but I think it might solve the problems

You dont need formidable if you use multer middleware. Multer will parse the input form and populate it in req.body as usual.The file data will be populated in req.files.

Related

return filename of uploaded file with multer and nodejs

I am creating a simple application as a learning experience with ionic 2 that connects to a node server running multer to upload images. The problem I am running into is, I need to get the final file name from multer back to the app that uploaded it, to save it locally. I am using the Auth and User modules from #ionic/cloud-angular for authentication and user information. The User object has a details object with things like "name", "email", "username", "image", ...
So, when an image is uploaded to the node server and multer saves it, I need to get that filename back to the application so I can update the user.details.image property.
Here is a simple version of my node server...
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var multer = require('multer');
var cors = require('cors');
var postStorage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './uploads');
},
filename: function(req, file, callback) {
let fileName = '', postName;
if(typeof req.body.postName !== "undefined") {
postName = req.body.postName.toLowerCase().replace(/ /g, '-');
filename += postName;
}
fileName += new Date().getTime();
fileName += ".png";
callback(null, fileName);
}
});
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cors());
app.post('/upload', function(req, res) {
var uploadPost = multer({storage: postStorage}).single('post_image');
uploadPost(req, res, function(err) {
if(err) {
return res.end("error uploading file");
}
res.end("file uploaded");
});
});
app.listen(app.get('port');
console.log("app listening on port: " _ app.get('port'));
Is there a way to have it send back the final file name that multer saved? Something like res.json({fileName: fileName}); res.end();
I really don't know at this point, and all the tutorials I can find on multer just show how to create a new filename and save a file in disk or database or memory, but nowhere does it show how you can actually get that filename back to the application that uploaded it.
Thank you in advance for any help, I really appreciate it. If you need to see the ionic 2 code that uploads the stuff please let me know and I will update the post with that code as well. Thank you.
If you are uploading single file you can get filename using req.file.filename
if you upload multiple files req.files
Once you got file name , you can send it to client using res.send({filename:FileName});

How to upload a picture using feathers.js and multer?

I'm working with feathers.js on the back-end and React on the front end and I need to implement a way to upload a picture. I'm using multer to handle the upload (and I've tried using busboy as well), but I can't seem to get the actual picture uploaded, or at least access it on req.file.
On the client side I have:
<form method="post" enctype="multipart/form-data" action="/picture/upload">
<input type="file" name="avatar" />
<input type="submit" value="Submit" />
</form>
In /src/middleware/index.js I have:
'use strict';
const uploadPicture = require('./uploadPicture');
const handler = require('feathers-errors/handler');
const notFound = require('./not-found-handler');
const logger = require('./logger');
var multer = require('multer');
const upload = multer({ dest: '../../client/img'});
module.exports = function() {
// Add your custom middleware here. Remember, that
// just like Express the order matters, so error
// handling middleware should go last.
const app = this;
app.post('/picture/upload', upload.single('avatar'), uploadPicture(app));
app.use(notFound());
app.use(logger(app));
app.use(handler());
};
This is src/middleware/uploadPicture.js:
'use strict';
module.exports = function(app) {
return function(req, res, next) {
console.log('req.file', req.file);
console.log('req.body', req.body);
};
};
req.file is always undefined, and req.body does contain the name of the image I uploaded.
I have tried using mutler and busboy on a basic Express project for testing, and it works perfectly, so that makes me think that maybe it has something to do with the middleware feathers.js uses and probably it changes some header or something, so multer can't append the file to the request object.
This is the order in which middleware is defined in src/app.js, which is where the server instance is run:
app.use(compress())
.options('*', cors())
.use(cors())
.use('/', serveStatic( app.get('client') ))
.use(bodyParser.json())
.use(bodyParser.urlencoded({ extended: true }))
.configure(hooks())
.configure(rest())
.configure(services)
.configure(middleware);
Any thoughts on how to handle the image upload in this scenario?
I am using react, so enctype is not a supported HTML attribute. I should have used encType in my form. That fixed the problem.

Storing a file into MongoDB using Multer in Mongoose

I have gotten this far to accept a file in my HTML form and post in with angular via an $http.post using the ng-file-upload module. Now I want to accept this file in Mongoose and store it into my NoSQL MongoDB hosted on MongoLab.
I have read about this module called Multer and followed the basic documentation, but it only me as far. Before I explain the beginning of the problem let me post my Code:
My HTML form:
<form name="upForm">
<fieldset>
<legend>Upload files here</legend>
<label>Insert File Here:</label>
<input type="file" ngf-select ng-model="exFile" name="file" ngf-accept="'.cs'" required>
<i ng-show="upForm.file.$error.required">*required</i>
<div class="alert" ng-show="file.$error === 'pattern'">
file type is not accepted
</div>
<br />
<button ng-disabled="!upForm.$valid" ng-click="uploadExercise(exFile)" class="btn btn-default">Submit</button>
<span class="progress" ng-show="picFile.progress >= 0">
<div style="width:{{exFile.progress}}%" ng-bind="picFile.progress + '%'"></div>
</span>
<span ng-show="picFile.result">Upload Successful</span>
</fieldset>
</form>
My Angular Code:
$scope.uploadExercise = function (file) {
console.log(file);
var fd = new FormData();
fd.append('file', file);
$http.post(url+"/Upload", fd,{
transformRequest: angular.identity,
header:{'Content-Type': undefined},
enctype:'multipart/form-data'
}).success(function () { }).error(function () { });
console.log(fd);
};
console logs return the correct file objects.
Mongoose so far:
var mongoose = require("mongoose");
var express = require("express");
var multer = require('multer');
var upload = multer({ dest: 'Uploads/' });
var bodyparser = require("body-parser");
var app = express();
mongoose.connect("connection-string");
app.use(bodyparser.json());
app.post('/Upload', upload.single('solution') ,function (req, res, next) {
console.log(req.file);
});
This console.log keeps returning undefined. So something, somewhere went terribly wrong. Please help me out!
I want to receive this file in my Mongoose and store it into the MongoDB, I have never done this before and can't seem to find any decent documentation for Multer or any decent explanation for storing files that is relevant for my case. What am I doing wrong? What should I be doing instead?
Man you are running on the wrong path. I have already explained in your previous question request that Multer is used to save files in file disk system and not to your database directly. For that you must use GRIDFS.
Coming to your current question.
app.post('/Upload', upload.single('solution') ,function (req, res, next) {
console.log(req.file);
});
Here the upload.single('solution') - calls a function Upload and the file name passed is solution but it is obvious enough that it isn't available here.
use this type of format - documentation of Multer
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
The Storage Part there is used to give path to where your file must be saved and the file name section is used to make changes to the file name that you would like to have.
Please read the documentation because that'll help. When we use third party modules we must acknowledge the information they have already given so that we can use their work easily.
Let me make it easier for you. Here is ready made code that works.
Multer throwing weird error while uploading file via ng-file upload
Go check that thread. The question was raised by me - the problem there was I was sending files in array format, as in multiple files at once. If you are not doing that just change ng-file-upload segment to use the single upload demo example and on server side nodejs code replace .array with .singleand things will work the way you want them to work - given that you want to use file disk system to store files.
I repeat that this method wont help you to save the file in mongodb directly.
Let me know if you need any further clarification.
After some research I found the answer to my problem. I'm able to store files into my MongoDB now. For those who are interested I'm posting my Mongoose code below with a small description.
Start by installing packages required for this operation. I used the following ones
npm install --save formidable
npm install --save gridfs
npm install --save fs
these are the packages I used ( Formidable, gridfs and fs).
this is the fully working mongoose code for me relevant to this particular form and request.
var mongoose = require("mongoose");
var express = require("express");
var formidable = require("formidable");
var fs = require("fs");
var grid = require("gridfs-stream");
var bodyparser = require("body-parser");
var app = express();
mongoose.connect("**fill in your connection-url here**");
var conn = mongoose.connection;
app.use(bodyparser.json());
app.post('/Upload', function (req, res) {
var form = new formidable.IncomingForm();
form.uploadDir = __dirname+"/Uploads";
form.keepExtensions = true;
form.parse(req, function (err, fields, files) {
if (!err) {
console.log('Files Uploaded: ' + files.file)
grid.mongo = mongoose.mongo;
var gfs = grid(conn.db);
var writestream = gfs.createWriteStream({
filename: files.file.name
});
fs.createReadStream(files.file.path).pipe(writestream);
}
});
form.on('end', function () {
res.send('Completed ... go check fs.files & fs.chunks in mongodb');
});
});
this worked for me! I now went to look in my mongoDB hosted on MongoLab and see that fs.chunks and fs.files collections were created and fs.files contains the correct data.
So for those who have this problem, this is a solution and the documentation on http://excellencenodejsblog.com/gridfs-using-mongoose-nodejs/ helped me out a lot. Now that I have this working, I also want to download the file FROM mongoDB onto a chosen directory on my pc, is there anyone who can give me the answer to that? or is that just as simple as to create a readstream to a file-system?

Retaining image file name and extension after upload in node.js (express) using multer

<!doctype html>
<html>
<body>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type='file' name="image">
<br>
<input type="submit" value="submit">
</form>
</body>
</html>
var express = require('express');
var router = express.Router();
var multer = require('multer');
var upload = multer({ dest: 'uploads/',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
} });
router.post('/upload', upload.single('image'), function(req, res){
res.send("Uploaded");
});
module.exports = router;
I have this basic code that uploads an image using the multer module. But when the file is uploaded it generates some random name and even gets rid of the file extension. It just says type 'file'. So how can I keep the image name with the extension.
when you upload file (using multer.single method), you get file data in
req.file
it is object which have in properties originalname, mimetype, path and others. Check docs for all : https://github.com/expressjs/multer
But dont trust mimetype.
How keep image name and extension?
a) rename uploaded file using data in req.file (dont like it)
b) store file data (req.file) in db
edit about rename:
when all downloaded files goes to one directory, and you change names to orginal, there may be conflicts - there may exists files with same names. Therefore, when you choose that way mayby you should move files to separate directories.
Next thing: Orginal file names may have insulting words or non standard chars (i dont know if it may be security isue) or be very long etc.
ok, how to rename?
we can use express package fs https://nodejs.org/api/fs.html
and methods:
fs.rename(oldPath, newPath, callback)
or
fs.renameSync(oldPath, newPath)

req.files is undefined when uploading file with multer

I am trying to build a Node.js Application in Express.js 4 that uploads an image. I decided to use the multer module but cannot access the uploaded file through req.files.
Here Is the code I am using. I restricted it to those parts that I believe are relevant.
Jade code:
form(method="POST", action="createPost", enctype="multipart/form-data")
input(type="file", name="photo")
br
input(type="submit" value="upload")
in routes/admin.js:
var express = require('express');
var multer = require('multer');
var router = express.Router();
var upload = multer({dest: './uploads/'});
router.post('/createPost', upload.single('photo'), function(req, res, next) {
console.log('files:', req.files);
console.log('body:', req.body);
// more code
}
output:
files: undefined
body: {}
The file is stored in the uploads folder but I cannot access its information in req.files. Can anyone help me?
When using upload.single(), per the multer documentation, the resulting file should be in req.file, not req.files. See the example in their doc here.
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})
And, here's the actual doc for upload.single():
.single(fieldname)
Accept a single file with the name fieldname. The single file will be
stored in req.file.

Categories

Resources