Download a file from NodeJS Server using hapi - javascript

I want to create a file download API using hapi.
Without using res.download(), how to do it using reply()?

You can also download a file from stream
const { Readable } = require('stream');
handler: async (request: any, h: Hapi.ResponseToolkit) => {
let stream = Fs.createReadStream(filePath);
let streamData = new Readable().wrap(stream);
return h.response(streamData)
.header('Content-Type', contentType)
.header('Content-Disposition', 'attachment; filename= ' + fileName);
}
To get content type of file you can refer:
getContentType(fileExt) {
let contentType;
switch (fileExt) {
case 'pdf':
contentType = 'application/pdf';
break;
case 'ppt':
contentType = 'application/vnd.ms-powerpoint';
break;
case 'pptx':
contentType = 'application/vnd.openxmlformats-officedocument.preplyentationml.preplyentation';
break;
case 'xls':
contentType = 'application/vnd.ms-excel';
break;
case 'xlsx':
contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
break;
case 'doc':
contentType = 'application/msword';
break;
case 'docx':
contentType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
break;
case 'csv':
contentType = 'application/octet-stream';
break;
case 'xml':
contentType = 'application/xml';
break;
}
return contentType;
}

you need to make a Buffer and then set the header and the encoding for the reply
let buf = new Buffer(xls, 'binary');
return reply(buf)
.encoding('binary')
.type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
.header('content-disposition', `attachment; filename=test-${new Date().toISOString()}.xlsx;`);

This solution is valid for hapi v17 and newer
You may use #hapi/inert module for downloading a file.
First, register the plugin with your server.
await server.register(require("#hapi/inert"));
Then in the handler
downloadFile: function (request, h) {
return h.file("name-of-file-to-download-from-local-system", {
mode: "attachment",
filename: "name-to-be-given-to-downloaded-file",
confine: "/path/to/file/", //This is optional. provide only if the file is saved in a different location
});
},
Detailed documentation is available here

Related

How can I stop CORS Error with embedded webcam PTZ CGI command [duplicate]

This question already has answers here:
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 3 years ago.
After upgrading to a new webcam I had to change my code that controls the PTZ on the web cam to:
function buttonDown(button) {
document.getElementById("status").innerHTML = "button " + button.id + " pressed";
$.get("http://192.168.1.111:88/cgi-bin/CGIProxy.fcgi?cmd=ptzMoveDown&user=user&pwd=pass", function() {
//on successful call
});
}
Now I get this error in the console:
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://192.168.1.111:81/decoder_control.cgi?command=0&user=user&pwd=password. (Reason: CORS request did not succeed). 2"
When I paste the URL with the CGI command in the browser windows everything works fine.
I read this solution stackflow solution but I dont understand or know how to implement it. Im not using node or js just html and javascript. What do I need to add to my web page to stop this error?
Found and easy solution based on the similiar stackoverflow answer from shaochuancs . I found a small proxy server proxy.js and this eliminates the CORS error.
Changed my function from:
function cam_down()
{
$.get("http://192.168.1.111:88/cgi-bin/CGIProxy.fcgi?cmd=ptzMoveDown&usr=user&pwd=pass&", function() {
});
To:
function cam_down()
{
$.get("http://localhost:9100/http://192.168.1.111:88/cgi-bin/CGIProxy.fcgi?cmd=ptzMoveDown&usr=user&pwd=pass&", function() {
});
Here is the proxy.js The code is run with node on the same webserver.
Yay Fixed !
// Simple proxy/forwarding server for when you don't want to have to add CORS during development.
// Usage: node proxy.js
// Open browser and navigate to http://localhost:9100/[url]
// Example: http://localhost:9100/http://www.google.com
// This is *NOT* for anything outside local development. It has zero error handling among other glaring problems.
// This started as code I grabbed from this SO question: http://stackoverflow.com/a/13472952/670023
var url = require('url')
, http = require('http')
, https = require('https');
var PORT = process.argv[2] || 9100;
var server = http.createServer(function(req, res) {
var reqUrl = req.url.substr(1);
console.log('==> Making req for' + reqUrl + '\n');
req.pause();
var options = url.parse(reqUrl);
options.headers = req.headers;
options.method = req.method;
options.agent = false;
options.headers['host'] = options.host;
var connector = (options.protocol == 'https:' ? https : http).request(options, function(serverResponse) {
console.log('<== Received res for', serverResponse.statusCode, reqUrl);
console.log('\t-> Request Headers: ', options);
console.log(' ');
console.log('\t-> Response Headers: ', serverResponse.headers);
serverResponse.pause();
serverResponse.headers['access-control-allow-origin'] = '*';
switch (serverResponse.statusCode) {
// pass through. we're not too smart here...
case 200: case 201: case 202: case 203: case 204: case 205: case 206:
case 304:
case 400: case 401: case 402: case 403: case 404: case 405:
case 406: case 407: case 408: case 409: case 410: case 411:
case 412: case 413: case 414: case 415: case 416: case 417: case 418:
res.writeHeader(serverResponse.statusCode, serverResponse.headers);
serverResponse.pipe(res, {end:true});
serverResponse.resume();
break;
// fix host and pass through.
case 301:
case 302:
case 303:
serverResponse.statusCode = 303;
serverResponse.headers['location'] = 'http://localhost:'+PORT+'/'+serverResponse.headers['location'];
console.log('\t-> Redirecting to ', serverResponse.headers['location']);
res.writeHeader(serverResponse.statusCode, serverResponse.headers);
serverResponse.pipe(res, {end:true});
serverResponse.resume();
break;
// error everything else
default:
var stringifiedHeaders = JSON.stringify(serverResponse.headers, null, 4);
serverResponse.resume();
res.writeHeader(500, {
'content-type': 'text/plain'
});
res.end(process.argv.join(' ') + ':\n\nError ' + serverResponse.statusCode + '\n' + stringifiedHeaders);
break;
}
console.log('\n\n');
});
req.pipe(connector, {end:true});
req.resume();
});
console.log('Listening on http://localhost:%s...', PORT);
server.listen(PORT);

prerender.io with native Node.js

Im trying to implement prerender.io for my Angular 1.6.0 app running on a native Node.js server
The documentation for setting up the middleware makes use of the connect middleware and specifically cites Express.js
app.use(require('prerender-node').set('prerenderToken', 'TOKEN'));
I am not using Express and was not using the Connect middleware to run my server.
My server.js is as follows:
var app = http.createServer(function(req, res){
var filePath = './debug/index.html';
var uri = req.url;
// Load index.html only when uri is not referencing a sub-directory of ./www (and is thus a URL)
for(i in dir){
if(uri.includes('/'+dir[i])) {
filePath = './debug'+uri;
break;
}
}
fs.exists(filePath, function(exists) {
if(exists){
fs.readFile(filePath, function(err, html) {
if(err){ res.writeHead(500); res.end(); }
else {
var ext = path.extname(filePath);
var contentType = 'text/html';
switch(ext) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.jpg':
contentType = 'image/jpeg';
break;
case '.png':
contentType = 'image/png';
break;
case '.svg':
contentType = 'image/svg+xml';
break;
case '.pdf':
contentType = 'application/pdf';
break;
default: contentType = 'text/html';
}
res.writeHead(200, { 'Content-Type': contentType });
res.end(html, 'utf-8');
}
});
} else {
res.writeHead(404);
res.end();
}
});
}).listen(port, function(){
console.log('server is running on port '+port);
});
1) How can I implement prerender.io with this configuration?
2) I did actually install Connect and trying to implement the middleware as follows:
var conn = connect();
conn.use(require('prerender-node').set('prerenderServiceUrl','http://localhost:3000/').set('prerenderToken', 'lqnF62jXABouJiFA2SuA'));
Which I just appended after the server code above.
I am not getting any errors but I do not see that anything at localhost:3000 after running node server. Although, my app runs fine on localhost:8080
How can I get prerender.io set up on this server?
You might could do something like the following, but I'd suggest breaking each function out into its own function to prevent all of the callbacks. Just wanted to leave the code alone so you could see where it was changed.
var prerender = require('prerender-node').set('prerenderToken', 'TOKEN');
var app = http.createServer(function(req, res){
prerender(req, res, function() {
var filePath = './debug/index.html';
var uri = req.url;
// Load index.html only when uri is not referencing a sub-directory of ./www (and is thus a URL)
for(i in dir){
if(uri.includes('/'+dir[i])) {
filePath = './debug'+uri;
break;
}
}
fs.exists(filePath, function(exists) {
if(exists){
fs.readFile(filePath, function(err, html) {
if(err){ res.writeHead(500); res.end(); }
else {
var ext = path.extname(filePath);
var contentType = 'text/html';
switch(ext) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.jpg':
contentType = 'image/jpeg';
break;
case '.png':
contentType = 'image/png';
break;
case '.svg':
contentType = 'image/svg+xml';
break;
case '.pdf':
contentType = 'application/pdf';
break;
default: contentType = 'text/html';
}
res.writeHead(200, { 'Content-Type': contentType });
res.end(html, 'utf-8');
}
});
} else {
res.writeHead(404);
res.end();
}
});
});
}).listen(port, function(){
console.log('server is running on port '+port);
});
As for your second question, you might have it installed correctly. Do you see a request on your prerender server console if you go to:
http://localhost:8080/?_escaped_fragment_=

meteor js how to write a file to local disk from the server?

I want to know how to save file in local disk? Like i want to save file in c: drive using meteor. Help me to achieve this.
Thanks in advance.
You can pass the data on the server methods than use file system you can write the file to a local disk.
Client side code :
Template code:
<template name="example">
<input type=file />
</template>
Template event code:
Template.example.events({
'change input': function(ev) {
_.each(ev.srcElement.files, function(file) {
Meteor.saveFile(file, file.name);
});
}
});
Meteor.saveFile function code:
/**
* #blob (https://developer.mozilla.org/en-US/docs/DOM/Blob)
* #name the file's name
* #type the file's type: binary, text (https://developer.mozilla.org/en-US/docs/DOM/FileReader#Methods)
*
* TODO Support other encodings: https://developer.mozilla.org/en-US/docs/DOM/FileReader#Methods
* ArrayBuffer / DataURL (base64)
*/
Meteor.saveFile = function(blob, name, path, type, callback) {
var fileReader = new FileReader(),
method, encoding = 'binary', type = type || 'binary';
switch (type) {
case 'text':
// TODO Is this needed? If we're uploading content from file, yes, but if it's from an input/textarea I think not...
method = 'readAsText';
encoding = 'utf8';
break;
case 'binary':
method = 'readAsBinaryString';
encoding = 'binary';
break;
default:
method = 'readAsBinaryString';
encoding = 'binary';
break;
}
fileReader.onload = function(file) {
Meteor.call('saveFile', file.srcElement.result, name, path, encoding, callback);
}
fileReader[method](blob);
}
Server side code :
/**
* TODO support other encodings:
* http://stackoverflow.com/questions/7329128/how-to-write-binary-data-to-a-file-using-node-js
*/
Meteor.methods({
saveFile: function(blob, name, path, encoding) {
var path = cleanPath(path), fs = __meteor_bootstrap__.require('fs'),
name = cleanName(name || 'file'), encoding = encoding || 'binary',
chroot = Meteor.chroot || 'public';
// Clean up the path. Remove any initial and final '/' -we prefix them-,
// any sort of attempt to go to the parent directory '..' and any empty directories in
// between '/////' - which may happen after removing '..'
path = chroot + (path ? '/' + path + '/' : '/');
// TODO Add file existance checks, etc...
fs.writeFile(path + name, blob, encoding, function(err) {
if (err) {
throw (new Meteor.Error(500, 'Failed to save file.', err));
} else {
console.log('The file ' + name + ' (' + encoding + ') was saved to ' + path);
}
});
function cleanPath(str) {
if (str) {
return str.replace(/\.\./g,'').replace(/\/+/g,'').
replace(/^\/+/,'').replace(/\/+$/,'');
}
}
function cleanName(str) {
return str.replace(/\.\./g,'').replace(/\//g,'');
}
}
});

Javascript: Detect if there is an image in the file reader

Is there a way to see if an image file is in the file reader in javascript?
You can try to determine if the file is an image by checking few bytes at the beginning of the stream. You can find the header signature of images easily by googling it.
This is a simple way to detect the image type:
reader.onload = function(e) {
var buffer = reader.result;
var int32View = new Int32Array(buffer);
switch(int32View[0]) {
case 1196314761:
file.verified_type = "image/png";
break;
case 944130375:
file.verified_type = "image/gif";
break;
case 544099650:
file.verified_type = "image/bmp";
break;
case -520103681:
file.verified_type = "image/jpg";
break;
default:
file.verified_type = "unknown";
break;
}
};
You can check few more bytes to give high accuracy to your results.

How to display image inside HTML document using node.js [duplicate]

This question already has answers here:
Node JS and Webpack Unexpected token <
(5 answers)
Closed 6 years ago.
I'm displaying some text that i've created inside HTML file using node.js (by method createServer).
Everything was working fine until i added picture inside the document, which doesn't get display on the site.
This is my code
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html'});
//read HTML
fs.readFile(__dirname + '//funkcionalnosti.html', function (err, data) {
console.log(data.toString());
res.end(data);
});
This is my code for image inside HTML file
And this is where picture is located
Picture as located same as HTML file, so i dont any ../ are necessary in order for it ti work. I've also tried adding the ful path and subdirectories but the picture won't show.
I've also tried this that i found on stackoverflow, but it's still not working
var image_origial = "diagram.jpg";
fs.readFile(image_origial, function (err, original_data) {
fs.writeFile('diagram.jpg', original_data, function (err) { });
var base64Image = original_data.toString('base64');
var decodedImage = new Buffer(base64Image, 'base64');
fs.writeFile('diagram.jpg', decodedImage, function (err) { });
});
Also tried this
res.write('<img src="data:diagram.jpg/;base64,imagedata">');
Or this
res.write('<img src="data:diagram.jpg/jpg;base64,imagedata">');
But no luck so far, please help me out, im desperate
Any help will be appreciated!!!
How is this a duplicate to "bundle.js:1 Uncaught SyntaxError: Unexpected token <" ?
You need something like this. You haven't handled route for the image that you are trying to access.
var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
console.log('request starting...');
var filePath = '.' + request.url;
if (filePath == './')
filePath = './index.html';
var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
contentType = 'image/jpg';
break;
case '.wav':
contentType = 'audio/wav';
break;
}
fs.readFile(filePath, function(error, content) {
if (error) {
if(error.code == 'ENOENT'){
fs.readFile('./404.html', function(error, content) {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
});
}
else {
response.writeHead(500);
response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
response.end();
}
}
else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');
Original Answer https://stackoverflow.com/a/29046869/2861108

Categories

Resources