Express js error when POST large arraybuffer - node.js

I use expressjs to upload large arraybuffer by POST and content-type is application/octet-stream.
I use middleware to read body content like that:
const getRawBody = require('raw-body');
/**
* Read body have content type is application/octet-stream
*/
app.use(function (req, res, next) {
if (req.headers['content-type'] === 'application/octet-stream') {
// using rawbody to read arrray buffer
getRawBody(req, {
length: req.headers['content-length'],
encoding: this.charset
}, function (err, string) {
if (err)
return next(err)
req.body = string
next()
})
}
else {
next()
}
});
When arraybuffer have large file(> 50MB). It's cant not read the body and return error to client(Chrome crashed, firefox xhr return error).
I don't know why. Please help me resolve this problem.
Many Thanks

Try following code snippet if it works.
app.use(express.bodyParser({limit: '100mb'}));

Related

Angular NodeJS Upload File and parameters together

I have been looking through multiple tutorials and stack overflow questions but for some reason I just cannot make this work. I have issues with uploading a file, so maybe fixing that first would solve the whole issue.
I tried a few options of sending a file from the front end to the back end, but it seems to always "get lost" before reaching the back end.
I have decided to use multer at the NodeJS backend to upload the file. Not sure if I am calling multer upload single right or not. Currently this is the code which I have for it:
const multer = require('multer');
const storage = multer.diskStorage({
destination: './uploadedImages',
filename: function(req,file,cb){
cb(null,file.originalname)
}
}) ;
const upload = multer({storage: storage})
exports.saveDrawing = async(req, res, next) => {
try
{
//save image
//tried a few different logs, but with FormData it seems like everything always empty
console.log("Image:");
console.log(req.body.drawingElement);
console.log(req.file);
upload.single('body.file');
return res.status(200).json({message: element});
}
}
catch (err)
{
console.log("Error at drawing save: " + err)
return res.status(500).json({message: "Error - Could not add/edit Drawing"});
}
}
And this is how it is sent from the Angular front end:
setDrawing(params, image): Observable<any> {
const formData = new FormData();
formData.append('file', image)
formData.append('data', params)
console.log("File: ");
console.log(formData.get('file'));
console.log("Data: ");
console.log(formData.get('data'));
return this.http.post<any>(`api/v1/structure/drawing/save`, formData);
}
At this stage printing out the data shows the right values. And the browser shows the right payload too:
At the back end I cannot see them in the req, req.body is empty, there is no req.form. For this api call before I have tried to include any files without the FromData I have accessed the data from req.body.
Am I looking for the data at the right place?
You're not using multer correctly, it's not doing anything.
To implement it as a middleware which you call from your handler, check the example from the docs
So, your handler should look something like this:
// setup multer middleware, set file field name
const upload = multer({storage: storage}).single('file');
exports.saveDrawing = async(req, res, next) => {
// now use the middleware, handle errors
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
return res.status(500).json({message: "Error - Could not add/edit Drawing"});
} else if (err) {
// An unknown error occurred when uploading.
return res.status(500).json({message: "Error - Could not add/edit Drawing"});
}
// Everything went fine.
console.log("Image:");
console.log(req.body.drawingElement);
console.log(req.file);
return res.status(200).json({message: element});
});
});

special characters are encoded in nodejs Express. how to decode it?

I tried following these instruction but couldn't get the URI decoded. how can I go about this?
When I enter a city like http://localhost:5000/weather?weatherCity=Malmö the URL changes to this http://localhost:5000/weather?weatherCity=Malm%C3%B6,
How can I decode the last part and what am I doing wrong?
app.get('/weather', (req, res) => {
const weatherCity = (req.query.weatherCity)
let decodeURI = decodeURIComponent(weatherCity) //<------- trying to decode the query
request(weatherURL(decodeURI), function (error, response, body) {
if (error) {
throw error
}
const data = JSON.parse(body)
return res.send(data)
});
})
function weatherURL(weatherCity){
return `https://api.openweathermap.org/data/2.5/weather?q=${weatherCity}&units=metric&appid=${process.env.APIKEY}&lang=en`
}
This is probably what you need:
app.get('/weather', (req, res) => {
const weatherCity = req.query.weatherCity;
request(weatherURL(weatherCity), function (error, response, body) {
if (error) {
throw error
}
const data = JSON.parse(body)
return res.send(data)
});
})
function weatherURL(weatherCity){
return `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(weatherCity)}&units=metric&appid=${process.env.APIKEY}&lang=en`
}
There should be no need to decode req.query.weatherCity because express does this automatically.
You do need to encode weatherCity before building a URL with it. URL query parameters should be URL encoded.
Consider using something other than request because it is deprecated and doesn't support promises. node-fetch and axios, among others, are good choices.

Why is my Express server response truncating during SSR only?

I am using Next.js, Redux, and Express. My page has this code:
static async getInitialProps({store, isServer, pathname, query}) {
const res = await fetch('http://localhost:3001/tutorials');
const tutorials = await res.json();
store.dispatch(tutorialsReceived({tutorials}));
}
I get the React debug error saying my server response is different than my client. It's expecting a very long JSON response (252KB), and the server render is getting cut off incredibly early. I have tried two ways to send the file and am unsure why either would cut short.
// Try 1
server.get('/tutorials', (req, res) => {
fs.createReadStream('./common/content.json').pipe(res);
});
// Try 2
server.get('/tutorials', (req, res) => {
fs.readFile('./common/content.json', 'utf8', function(err, tutorials) {
res.send(tutorials);
});
});
Modifying the file to be smaller like {a:1,b:2,c:3} results in no error for my sanity check.
Looks like express is setting wrong Content-Length header in the response due to which your JSON gets chopped off. You can set it explicitly and that should work.
server.get('/tutorials', (req, res) => {
fs.readFile('./common/content.json', 'utf8', function (err, tutorials){
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(tutorials, 'utf8')
})
res.send(tutorials);
});
});

Changing the header of the response on NodeJS using request

I have the following problem:
I want to get a static file from another server, and give it back to the user with another content-type header.
The following code works just fine, but I can't figure out a way to change the response header, though.
const request = require('request');
app.get('video', function (req, res) {
request.get('http://anotherurl.com/video-sample.mp4').pipe(res);
});
I tried to do this thing more manually, but the response was very slow.
app.get('video', function (req, res) {
request.get('http://anotherurl.com/video-sample.mp4', function(error, response, body) {
// ...
res.setHeader('content-type', 'image/png');
res.send(new Buffer(body));
});
});
Can you guys help me with that?
Thanks
Just set the response header when the 'response' event fires.
app.get('video', (req, res) => {
request.get('http://anotherurl.com/video-sample.mp4')
.on('response', response => {
res.setHeader('Content-Type', 'image/png');
// pipe response to res
// since response is an http.IncomingMessage
response.pipe(res);
});
});

NodeJs: Sending picture with Express (Multer)

I have this code
app.get('/imgs/:id', function(req, res) {
// Validate that req.params.id is 16 bytes hex string
// Get the stored image type for this image
var stream = fs.createReadStream(path.join(UPLOAD_PATH, req.params.id));
stream.on("readable", function() {
res.setHeader('Content-Type', "image/jpeg")
stream.pipe(res)
})
stream.on('error', (e) => {
res.redirect(404, "404")
})
});
Now the problem is that I always get an error of
Error: Can't set headers after they are sent.
because I used the res.setHeader function.
However, i don't know how to solve it. Let's say I want to use in a page, that has obviously the res.send() function has well,
the <img src="imgs/pic">, then I must set the header for the this page request to "image/jpeg" because otherwise the browser wouldn't know it's an image and won't show it as one.
What can I do then?
Check Express response document here. Try this code
app.get('/imgs/:id', function (req, res) {
res.sendFile(req.params.id, {root: UPLOAD_PATH, headers: {'Content-Type': 'image/jpeg'}}, function (err) {
if(err) throw err;
else console.log('sent')
})
})

Resources