I'm make api to upload files using node js.
i using multer for handle multipart/form-data
but when i console.log(req.file) it appears undefined
Route
const uploadController = require('../controller/upload.server.controller');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
/**
* Routes
*/
module.exports = function (app) {
app
.route('/api/upload')
.post(upload.single('image'), uploadController.upload);
};
Controller
exports.upload = async function (req, res) {
console.log(req.file);
};
my request with postman
Try using req.file as per the docs source: multer
// init
const multer = require('multer');
const path = require('path');
// "images" are the folder name
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'images');
},
});
// put this to config the multer
app.use(multer({ storage: fileStorage }).single('image'));
// this is for serving file staticly with "path" module
app.use('/images', express.static(path.join(__dirname, 'images')));
Also make sure you write enctype=multipart/form-data in the form tag not in the input tag AND
add type=file attribute in the input tag
Try this:
app.post('/api/upload', upload.single('image'), function (req, res, next) {
console.log(req.file);
})
I have also encountered similar problem. Everytime I restart my server postman provided req.file gives undefined. I thought maybe I habe made a bug but I couldn't figure out what was wrong.
Then I tried creating a new request in postman and when I requested req.file works perfectly. I am trying to figure out what is wrong with Postman or am I making a mistake while sending a request.
Related
I am trying to test REST API, and I can't figure out how to send a file from client side to express server side.
This is my pug file, with which i simulate client side for specific purposes, in this case just send the picture.
doctype html
html
head
title Test
body
form(action=`${baseRoute}/api/users/${nick}/generate` enctype="multipart/form-data" method='POST')
input(type='file' accept="image/png, image/jpeg" id='profile_picture' name='image')
input(type='submit', value='Load')
baseRoute is created for pug, so it does not add action link to existing link, and changes the whole link.
From what I saw, to get files from form, I have to access req.files in express back end part. Yet, it shows me absolutely nothing
const express = require('express');
const app = express();
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.set('views', 'views');
app.set('view engine', 'pug');
app.get('/', function(req, res, next) {
res.redirect('/test/update_user');
});
app.post('/api/users/:nick/generate', upload.single('image'), async function(req, res, next) {
console.log("GENERATE USER");
console.log(req.files);
res.send("Success");
});
app.get('/test/update_user', function(req, res, next) {
let params = {
baseRoute: "",
nick: 'somenick',
};
res.render('test/update_user', params);
});
app.listen(3000, () => {
console.log("go to localhost:3000/test/update_user");
});
I tried reading all of req, but there was no sight of files property. Using multer it adds a file to upload directory, but in a weird way without any extension and some weird name. And still it logs 'undefined' when I am trying to access req.files
In Node Js, on the entry file e.g. index.js, How can I get requested data either as Form-data or Form-URL-encoded or Raw JSON data in middleware?
In my project, I am handling various API request,
Few requests contain file type so requesting as form-data.
Few requests do not contain file type so requests are coming as Form-URL-encoded.
Now the main problem is before routing, I need a specific field from req.body in the middleware.
But I am getting req.body as undefined.
For reference here is my index.js file:
const express = require('express');
const app = express();
app.use(express.raw());
app.use(express.urlencoded({ extended: false }));
app.use((req, res, next) => {
const routes_handler = require('./routes/index.js')(app, express, req);
next();
})
app.listen(3000, () => {
console.log("Server running at Port " + 3000);
});
and the routes/index.js file as follows:
module.exports = function (app, express, req) {
console.log(req.body);
//I need here data of req.body for all requests type (form data, URL-encoded, raw JSON)
app.post('/', function (req, res) {
console.log("Here I can get the requested body easily", req.body)
res.send('Hello World');
});
app.post('*', function (req, res) {
res.send({
code: 0,
message: 'No Content',
status_code: 204,
data: {
error: 'API not found!'
}
});
});
}
Also, I know for file type data, POSTMAN will send the request as Form-data, not as Form-url-encoded. So which I should choose Formidable or Multer?
The way you get all the data in index.js is by creating middlewares for your application, every time any routes that go into your application will be passed through this middleware.
Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.
The below middleware will simply listen to all routes & adds up request time to request time, here goes the code
let express = require('express')
let app = express()
let bodyParser = require("body-parser")
app.use(bodyParser.json())
let requestTime = function (req, res, next) { // simply updating add the requestBody using the middleware
req.requestTime = Date.now();
req.json_body = req.body;
next()
}
app.use(requestTime) // requestTime is the middleware here
app.get('/', function (req, res) {
var responseText = 'Hello World!<br>'
responseText += '<small>Requested at: ' + req.requestTime + '</small>'
res.send(responseText)
})
app.listen(3000)
Few things to note here
Always add interceptor above all routes
Don't forget to add next() inside the middleware, else it will not go to the next route.
Now, coming to the second part of your question which is accessing body,formdata, etc
You can use body-parser npm module to achieve that, something like this
Starting from Express 4, body-parser comes inbuilt with it, so you can try out something
app.use(express.json());
app.use(
bodyParser.urlencoded({
extended: false
})
);
Now, the last bit, you don't need Multer for formdata, but for file upload like multipart/form-data you will need this. Both are good in their own ways, I would go for Multer.
Hope this will help you :)
I believe the body-parser module is your answer.
https://www.npmjs.com/package/body-parser
Add the following line before the routes in your index.js after installing the body-parser package.
app.use(bodyParser.json())
I am posting a large number of files that can take potentially minutes to upload. I using a multi-part form to post the files and then waiting for a response from the POST, but this can take several minutes.
How do I make Node/Express wait for this response? As of now, it seems like the request is "timing out" and Node or the browser is re-POSTing the files because it is taking so long. I can see this because my middleware functions are being called multiple times for requests that take too long.
Is there a library to make Node not timeout? Should I be attempting to POST these files in a different fashion? Thanks
var mid = function(req,res,next) {
console.log('Called');
next();
};
app.post('/api/GROBID', mid, authenticate, PDFupload.return_GROBID, PDFupload.post_doc, function(req, res) {
if (res.locals.body == 400) res.send(400);
/*if (process.env.TEST_ENV == 'unit-testing') {
res.send(res.locals.body);
}*/
res.render('uploads', {files : res.locals.body});
});
Edit: This mid middleware (used as an example) is being called twice. This means the route is being posted to twice. How do I make sure this does not happen?
Is there a library to make Node not timeout?
Express sits on top of Node.js' built-in HTTP server. By default, the timeout is 2 minutes. You can modify its default timeout as below:
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
app.get('/', function(req, res) {
res.send('<html><head></head><body><h1>Hello world!</h1></body></html>');
});
var server = app.listen(port);
server.timeout = 1000 * 60 * 10; // 10 minutes
Should I be attempting to POST these files in a different fashion?
Yes, you can use Multer, a node.js middleware for handling multipart/form-data, which is primarily used for uploading files.
And with Multer, you don't have to worry about the timeout anymore. Event the upload time is longer than the timeout, say 2 minutes by default, Express just won't timeout.
Here is the sample code:
app.js
var express = require('express');
var app = express();
var path = require('path');
var multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/your/path/to/store/uploaded/files/')
},
filename: function (req, file, cb) {
// Keep original file names
cb(null, file.originalname)
}
})
var upload = multer({ storage: storage })
// files is the name of the input html element
// 12 is the maximum number of files to upload
app.post('/upload', upload.array('files', 12), async (req, res) => {
res.send('File uploaded!');
})
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.listen(3000);
index.html
<html>
<body>
<form ref='uploadForm' id='uploadForm'
action='http://localhost:3000/upload'
method='post'
encType="multipart/form-data">
<input type='file' name='files' multiple/>
<input type='submit' value='Upload!' />
</form>
</body>
</html>
Now try starting the web server:
node app.js
Then open your browser and go to http://localhost:3000
You can now upload a number of big files, which you can find later on in folder /your/path/to/store/uploaded/files/
I am facing issue while file upload in express.js with multer.
I have written below code in my route.js:
var multer = require('multer');
var upload = multer({dest: 'uploads/'});
module.exports = function(router) {
router.post('/route/file', upload.single('file'), function(req, res) {
// this is not called..
console.log('this should be called');
});
}
It's strange in my windows it's working fine. But in my MacBook same code isn't working.
I am getting my head around node.js and trying to construct a post request, this is my server.js file:
module.exports = function(app) {
app.post('/api/postrequest', function(req, res) {
console.log('inside postrequest');
console.log(req.body); //this is empty????
});
// application -------------------------------------------------------------
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
};
I would like to filter data from the request so try to verify what is in req.body. The problem is it is empty : {}. To test I am using Postman to submit the request:
http://localhost:8080/api/postrequest
Using the raw format to post this json:
{"name":"Eddie"}
You will need to use a middleware like body-parser to do that. Do an npm install body-parser and require it in your app with
var bodyParser = require('body-parser');
Then use it like so
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended': 'true'}));