I have a toy react app that asks a toy nodejs server to do some image processing and return the result. The image processing server does this:
let result = path.join(__dirname, '/../../tmp/', name)
// .. write image to result
res.status(200).sendFile(result)
Logging this response on the client, I get:
{ data: "...binary image stuff...", status: 200, etc }
(1) How do I get that image data in data into an <img> tag in JSX? src={response.data}? that doesn't work
(2) Am I going about this wrong? Is the better way to just answer the filename in tmp then have the img src refer to that path? This idea seems better, except I'll get no chance to clean up the tmp file because I won't know when the img tag has finished getting it.
If there's a better way than (1) or (2) (like maybe a stream?) that would be great to understand, too. Thanks.
If you use express js you have send image files easily.
Example,
// server.js
var express = require('express');
var path = require('path');
app.use('/app', function(req, res){
res.sendFile(path.resolve(__dirname, './html/app.html'));
})
app.use('/image', function(req, res){
res.sendFile(path.resolve(__dirname, './images/img1.jpg'));
})
app.listen(9090, function(err){
if(err){
console.log(err);
}
console.log('Listening at localhost:9090');
})
// app.html html/app.html
<html>
<body>
<img src='/image'/>
</body>
</html>
// img1.jpg images/img1.jpg
Your images has inside this folder.
Run your server and hit http:localhost:9090/app the app.html is open with image.
I hope this is useful for you.
Related
I have followed a tutorial to produce a Twitter bot using node.js, github and Heroku. Everything works great, the bot pulls a random image from a folder at timed intervals and tweets the image.
I'm trying to change the process so that instead of pulling images from a local folder (called 'images'), it pulls them from a web hosted folder. For example, rather than get the images from the local /images folder, I'd like it to pull the image from http://mysite/images. I have tried changing what I think are the relevant bits of code below, but am having no luck. Could anybody offer some advice please?
The whole code is below, but for reference, the bits I have tried changing are:
var image_path = path.join(__dirname, '/images/' +
random_from_array(images))
and
fs.readdir(__dirname + '/images', function(err, files) {
In both cases above I tried changing the /images folder to http://mysite/images but it doesn't work. I get an error stating that no such folder can be found. I have tried changing/deleting the __dirname part too but to no avail.
Any help appreciated!
Full code below:
const http = require('http');
const port=process.env.PORT || 3000
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end('<h1>Hello World</h1>');
});
server.listen(port,() => {
console.log(`Server running at port `+port);
});
var Twit = require('twit')
var fs = require('fs'),
path = require('path'),
Twit = require('twit'),
config = require(path.join(__dirname, 'config.js'));
var T = new Twit(config);
function random_from_array(images){
return images[Math.floor(Math.random() * images.length)];
}
function upload_random_image(images){
console.log('Opening an image...');
var image_path = path.join(__dirname, '/images/' +
random_from_array(images)),
b64content = fs.readFileSync(image_path, { encoding: 'base64' });
console.log('Uploading an image...');
T.post('media/upload', { media_data: b64content }, function (err, data,
response) {
if (err){
console.log('ERROR:');
console.log(err);
}
else{
console.log('Image uploaded!');
console.log('Now tweeting it...');
T.post('statuses/update', {
/* You can include text with your image as well. */
// status: 'New picture!',
/* Or you can pick random text from an array. */
status: random_from_array([
'New picture!',
'Check this out!'
]),
media_ids: new Array(data.media_id_string)
},
function(err, data, response) {
if (err){
console.log('ERROR:');
console.log(err);
}
else{
console.log('Posted an image!');
}
}
);
}
});
}
fs.readdir(__dirname + '/images', function(err, files) {
if (err){
console.log(err);
}
else{
var images = [];
files.forEach(function(f) {
images.push(f);
});
/*
You have two options here. Either you will keep your bot running, and
upload images using setInterval (see below; 10000 means '10 milliseconds',
or 10 seconds), --
*/
setInterval(function(){
upload_random_image(images);
}, 30000);
/*
Or you could use cron (code.tutsplus.com/tutorials/scheduling-tasks-
with-cron-jobs--net-8800), in which case you just need:
*/
// upload_random_image(images);
}
});
Well, my first answer to a question about building a twitter bot would probably be: "Don't do that!" (Because the world doesn't need more twitter bots.) But, putting that aside...
Your code is using the "fs" library, which is exactly what you needed for grabbing stuff from the local file system. That was fine. But now you want to grab stuff from web servers, which "fs" is not going to be able to do. Instead, you need a library that gives you the ability to make an HTTP or HTTPS request across the web and bring you back some data. There are different libraries that do this. Looks like you are already bringing in the "http" library, so I think you are on the right track there, but you seem to be using it to set up a server, and I don't think that's what you want. Rather, you need to use http as a client, and replace your fs.readFileSync() calls with the appropriate calls from the http library (if that's the one you choose to use) to pull in the data you want from whatever server has the data.
Hope that helps. And I hope your twitter bot is going to be a good little bot, not an evil one!
I uploaded image using multer,node.js,mongodb.
I uploaded the image in upload folder and I stored the path in MongoDB.
this is my folder structure
server is running
http://localhost:3000/images/590051dcc90cf702e452b9c1
based on document id I am retriving document
// To get the single image/File using id from the MongoDB
app.get('/images/:id', function(req, res) {
//calling the function from index.js class using routes object..
routes.getImageById(req.params.id, function(err, genres) {
if (err) {
throw err;
}
//res.download(genres.path);
res.send(genres)
});
});
I got response like this
{"_id":"590051dcc90cf702e452b9c1","path":"uploads\login.jpg","name":"asdf","email":"asdf#gmail.com","originalname":"login.jpg","__v":0}
I am sending the above response to angular and andriod application.
now I want to display this image in angular .
angular server is working in diffrent server node server is working in different server
i put like this
</head><body>
<body ng-controller="RegisterCtrl" ng-app="myApp">
<div ng-init="signin()">
<img ng-src="{{response.path}}"/>
{{response}}
</div>
</body>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js'></script>
<script>var myApp = angular.module('myApp', []);
myApp.controller('RegisterCtrl', function ($scope,$http) {
$scope.signin = function()
{
$http.get('http://localhost:3000/images/590051dcc90cf702e452b9c1').success(function(data, response)
{
$scope.response = data;
console.log(data);
});
}
});
</script>
</body></html>
i am getting error
file:///C:/Users/mohan/Desktop/uploads/login.jpg net::ERR_FILE_NOT_FOUND
bcoz file is located in server side
On Node JS server convert the get api method to fetch the image path from Mongo Db and return the byte array of the image.
// To get the single image/File using id from the MongoDB
app.get('/images/:id', function(req, res) {
//calling the function from index.js class using routes object..
routes.getImageById(req.params.id, function(err, genres) {
if (err) {
throw err;
}
//res.download(genres.path);
var fs = require('fs');
// read binary data
var bitmap = fs.readFileSync(genres.path);
// convert binary data to base64 encoded string
//res.send(new Buffer(bitmap).toString('base64'));
genres.path = new Buffer(bitmap).toString('base64');
res.send(genres)
});
});
Bind this byte array to your tag.
<img ng-src="{{'data:image/png;charset=utf-8;base64,' + response.data.path}}">
Just assign the path to image using ng-src
Assume this is the response json
$scope.response = {"_id":"590051dcc90cf702e452b9c1","path":"uploads\login.jpg","name":"asdf","email":"asdf#gmail.com","originalname":"login.jpg","__v":0}
in the image tag.
<img ng-src"{{response.path}}">
You can use <img ng-src="{{response.path}}"/>
Could you please confirm whether the image is available in the url, 'http://localhost:3000/uploads/login.jpg'?
If not, the image path is not correct. Please check whether it is uploaded into the folder correctly.
I have a Node.js process which outputs a video stream into my Node.js app.
On the client end, there is a <video> tag. I would like to stream the video from Node.js into the src attribute of the video tag. My previous experience tells me that we must use the blob object for this. However, I'm not a hundred percent certain how and why I would use it.
Another possible solution I'm thinking of is to create some sort of a temporary file on my server, then write the stream to that file, then serve that file as the source for the video. However, that doesn't seem intuitive. I was wondering, then, if there is a more established solution for an issue like this.
m3u8 format is commonly used for streaming.
Video streaming/transcoding is a resource intensive thing. I would suggest you to use third party service to do so, if you have that option.
Probably you might want to look at the following options:
BinaryJS. It's bidrectional realtime binary data transfer tool based on websockets.
JSMpeg stream-server (in case of capturing) from Phoboslab guys. All you need to do is start ffmpeg and point it to the domain and port where the nodejs script is running.
More info you can find here.
Pipe a stream directly. Good answer is posted here. In few words you just need to specify Accept-Ranges, Content-Range, Content-Length and Content-Type headers, then create relevant Read stream (with start and end options) and pipe it to the response object.
I've actually tried this at a hackathon two weeks ago. I ended up barely getting this flv stream to work, which I've posted below. My intent was to make a library to automate much of the processes this would entail.
As you can see, I've opened a new port on the server to handle the separate stream of data flowing to the client. This is reflected in the client's src tag.
THREE THINGS YOU NEED:
This Linux version of ffmpeg.
Flowplayer on the js side.
npm fluent-ffmpeg
// StreamServer.js
var express = require('express'),
app = express(),
ffmpeg = require('fluent-ffmpeg');
module.exports = function () {
app.stream(req, res)
{
res.contentType('flv');
// make sure you set the correct path to your video file storage
var pathToMovie = '/path/to/storage/' + req.params.filename;
var proc = ffmpeg(pathToMovie)
// use the 'flashvideo' preset (located in /lib/presets/flashvideo.js)
.preset('flashvideo')
// setup event handlers
.on('end', function () {
console.log('file has been converted succesfully');
})
.on('error', function (err) {
console.log('an error happened: ' + err.message);
})
// save to stream
.pipe(res, { end: true });
};
}
//routes.js
'use strict';
var stream = require('../controllers/streaming.server.controller'),
streamServer = require('../controllers/StreamServer.js'),
express = require('express');
//streaming.server.controller.js
module.exports = function (app) {
app.get('/api/stream', function (req, res) {
streamServer.stream(req, res);
});
};
var path = require('path'),
express = require('express'),
app = express(),
routes = require('../routes/routes.js')(app),
ffmpeg = require('fluent-ffmpeg');
app.listen(4000);
EDIT: Client side part:
https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/tree/master/examples/flowplayer
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="/flowplayer.min.js"></script>
<title>node-fluent-ffmpeg</title>
</head>
<body>
<!-- this A tag is where your Flowplayer will be placed. it can be anywhere -->
<a
href="http://localhost:4000/api/stream"
style="display:block;width:520px;height:330px"
id="player">
</a>
<!-- this will install flowplayer inside previous A- tag. -->
<script>
flowplayer("player", "/flowplayer.swf");
</script>
</body>
</html>
(Just change the href attribute)
I'm building a Meteor app that communicates with a desktop client via HTTP requests with https://github.com/crazytoad/meteor-collectionapi
The desktop client generates images at irregular time intervals, and I want the Meteor site to only display the most recently generated image (ideally in real time). My initial idea was to use a PUT request to a singleton collection with the base64 imagedata, but I don't know how to turn that data into an image in the web browser. Note: the images are all pretty small (much less than 1 MB) so using gridFS should be unnecessary.
I realize this idea could be completely wrong, so if I'm completely on the wrong track, please suggest a better course of action.
You'll need to write a middleware to serve your images with proper MIME type. Example:
WebApp.connectHandlers.stack.splice (0, 0, {
route: '/imageserver',
handle: function(req, res, next) {
// Assuming the path is /imageserver/:id, here you get the :id
var iid = req.url.split('/')[1];
var item = Images.findOne(iid);
if(!item) {
// Image not found
res.writeHead(404);
res.end('File not found');
return;
}
// Image found
res.writeHead(200, {
'Content-Type': item.type,
});
res.write(new Buffer(item.data, 'base64'));
res.end();
},
});
I'm trying to learn nodejs and I thought the best way to do this would be to try doing some stuff without using express or any other non-core modules. I'm stuck on trying to get some text and an image to be delivered simultaneously. The code I'm trying is:
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(request,response) {
fs.readFile('my_pic.jpg', function(error, file) {
response.writeHead(200, {'content-type':'text/html'});
response.write('<p>hi there!</p>');
response.writeHead(200, {'content-type':'image/jpg'});
response.write(file, 'image');
response.end();
});
});
var port = process.env.PORT || 8080;
server.listen(port, function() {
console.log('Listening on port ' + port);
});
So ideally what should be delivered is:
<html>
<body>
<p>hi there</p>
<img src='my_pic.jpg'/>
</body>
</html>
But instead, nothing is appearing.
I tried putting a response.end() after writing 'hi there', which displays the text, and after that I tried swapping the places of the text and picture (headers included), which displayed the picture, but I can't figure out how to get both to display simultaneously, like on a real web page.
Can you explain how to go about putting in different types of content onto the same webpage - do they need to be in different responses? Something I came across on another question:
nodejs - How to read and output jpg image?
Something like that looks like the solution, but I can't figure out how to apply this to my situation (I don't have a lot of experience in the server side of things.)
Many thanks
EDIT: got it working from user568109's reply:
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(request,response) {
fs.readFile('my_pic.jpg', function(error, file) {
var imagedata = new Buffer(file).toString('base64');
response.writeHead(200, {'content-type':'text/html'});
response.write("hi there!<img src='data:my_pic.jpg;base64,"+imagedata+"'/>");
response.end();
});
});
var port = process.env.PORT || 8080;
server.listen(port, function() {
console.log('Listening on port' + port);
});
This seems like a lot of work in embedding images though - if I wanted to put more than one image in, I'd have to just keep nesting those filestream callbacks?
I also tried it this way but it doesn't work:
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(request,response) {
response.writeHead(200, {'content-type':'text/html'});
response.write("hi there!<img src='my_pic.jpg'/>");
response.end();
});
var port = process.env.PORT || 8080;
server.listen(port, function() {
console.log('Listening on port' + port);
});
I wasn't sure if this was what people meant by the line
response.write('<img src="my_pic.jpg"/>')
, because the server doesn't seem to be making another request on my behalf to go fetch the image? It's just showing a broken icon image.
If you do response.write('<img src="my_pic.jpg"/>'); as mentioned above the image file would be sent only when browser sends GET for the image. It would become multi-part request.
Or you can do it like this. It is possible to send your image in binary form in HTML. Use :
<img src="data:image/gif;base64,imagedata">
where imagedata is a base64 encoding of gif image. So do this in node.js :
//Write text in response.
content = get-image-file-contents; //store image into content
imagedata = new Buffer(content).toString('base64'); //encode to base64
response.write('<img src="data:image/gif;base64,'+imagedata+'">');//send image
response.end();
Check here for correct image conversion NodeJS base64 image encoding/decoding not quite working
This sends one response which sends both text and image. Only one header is required for response response.writeHead(200, {'content-type':'text/html'});
You can only write one value to a given header, so the second header is overwriting the first. Two solutions are
write out a url to the image in the html - will be slightly slower for the user (needing an extra http request to fetch the image), but depending on the use case this is normally acceptable and very simple to implement
convert the image to a data-uri string and include this in the html as the source of the image. More complicated to implement than the first approach ( I don't know of any libraries for doing the conversion in node) and with negligible benefits.