I'm running a Node Server that I want to stream videos from magnet links that uses WebTorrent(https://webtorrent.io/docs). When I run this, it appears as if the file is not being correctly referenced even though I have set a variable as the .mp4 file.
Just to be clear, I added in a given torrentID(magnet link) in this example to eliminate any problems I may have with express and the URLs. This magnet link leads to a download of a music video in MP4 format.
The video player is showing up, but no video is being played. I'm assuming this means that I am not trying to access the correct file. If you need to know more about WebTorrent to help me, you can read about it at https://webtorrent.io/docs
var fs = require("fs"),
http = require("http"),
url = require("url"),
path = require("path"),
request = require('request'),
host = '127.0.0.1',
port = 3000,
express = require("express"),
app = express(),
server = http.createServer(app),
WebTorrent = require('webtorrent'),
client = new WebTorrent();
app.get('/streamvid/:magLink', function(req, res){
//var torrentID = req.params.magLink;
var torrentID = 'magnet:?xt=urn:btih:84123E8B4E850A796403736E0CF02E409F0EF00B';
client.add(torrentID, function (torrent) {
var file = torrent.files[0]
file.name = 'movie.mp4';
if (req.url != "/movie.mp4") {
res.writeHead(200, { "Content-Type": "text/html" });
res.end('<video width="1024" height="768" controls> <source src="movie.mp4" type="video/mp4"> <source src="movie.ogg" type="video/ogg"> Your browser does not support the video tag. </video>');
} else {
var range = req.headers.range;
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0], 10);
fs.stat(file, function(err, stats) {
var total = stats.size;
var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
var chunksize = (end - start) + 1;
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
var stream = fs.createReadStream(file, { start: start, end: end })
.on("open", function() {
stream.pipe(res);
}).on("error", function(err) {
res.end(err);
});
});
}
})
});
var server = http.createServer(app);
var server = app.listen(port, host);
server.on('error', function(err) {
console.log('error:' + err);
});
server.on('listening', function(){
console.log('Server is Up and Running');
});
You need to either pipe the file data by reading it.
var readFile = fs.createReadStream("path/to/movie.mp4");
readFile.pipe(res);
Or have the file in a public route. app.use(express.static('public')) and put movie.mp4 in the public/ folder. Then in your src, do a full url link. http://localhost:3000/movie.mp4.
Related
I am trying to create a web page in node.js which lists all pdf files in a folder defined by a variable in the URL. When a user clicks on one pdf link, the file should open.
Sadly, being a total node.js/javascript beginner, I can't figure out how to do it.
URL: http://127.0.0.1:3000/?id=1001
OS: Windows Server 2012 R2
Steps which should be done:
The "id" variable has to be read from the URL
Then, only the .PDF files in the directory ./files/id/ have to be read and listed -- where "id" is the variable from 1.
Then, when the user clicks one of them, it should open in the browser (Chrome)
What I managed to do:
set up the web server
parse the URL for the id value
dir the id folder
display the files
Below the code:
const
http = require('http'),
hostname = '127.0.0.1',
port = 3000,
querystring = require('querystring'),
url = require('url'),
fs = require('fs');
const server = http.createServer((req, res) => {
const params = querystring.parse(url.parse(req.url).query);
if ('id' in params) {
let html = "Test page\n"
html += "id: " + params.id + "\n";
const pdfdir = "./files/" + params.id + "/";
console.log(pdfdir);
let files = fs.readdirSync(pdfdir);
files.forEach(file => {
const filepath = __dirname + pdfdir + file;
console.log(filepath);
html += "File: " + pdfdir + file + "\n";
});
res.write(html);
}
else {
res.write('Incorrect link');
}
res.end();
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Can somebody please guide me with the next steps?
// imports first
const
http = require('http'),
url = require('url'),
querystring = require('querystring'),
fs = require('fs'),
path = require('path');
const
hostname = '127.0.0.1',
port = 3000;
// main function should only route requests
const server = http.createServer((req, res) => {
const params = querystring.parse(url.parse(req.url).query);
if ('id' in params) {
handleDirectoryListing(req, res, params)
} else if ('file' in params) {
handleServeFile(req, res, params)
} else {
res.statusCode = 404
res.end('Incorrect link');
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
function handleDirectoryListing (req, res, params) {
const pdfdir = `./files/${params.id}/`;
console.log(pdfdir);
// never use sync in an http handler
fs.readdir(pdfdir, function (err, files) {
if (err) {
res.statusCode = 404;
res.end('directory not found');
} else {
let html = `<!DOCTYPE html>
<meta charset="utf-8">
<title>Test page</title>
<h1>Test page</h1>
<div>id: ${params.id}</div>
`;
html += files.map(file => {
const filepath = path.join(pdfdir, file);
console.log(filepath);
return `<dir>File: ${pdfdir}${file}</dir>`;
}).join('\n');
res.end(html);
}
});
}
// serving files is easy, but note, this is not secure or efficient
function handleServeFile (req, res, params) {
const filepath = path.join(__dirname, params.file);
fs.createReadStream(filepath).pipe(res);
}
Though once you grasp it you should use a module such as express to make it clean, secure, efficient etc . . .
I managed to get the number of peers connected in my console log by having the console print out "You are peer number n" for each new connected peer.
Is there a way of adding the id of each connected peer too?
I'm relatively new with socket.io and I can't seem to find a way to do this.
This is my server.js file:
var app = require("express")();
var express = require("express");
var server = require("http").Server(app);
var p2pserver = require("socket.io-p2p-server").Server;
var io = require("socket.io")(server);
var ss = require("socket.io-stream");
var path = require("path");
app.use(express.static(__dirname));
io.use(p2pserver);
var peerNum = 0;
io.on("connection", function(socket) {
console.log("Peer " + peerNum + " connected");
io.emit("peer-num", peerNum);
peerNum++;
ss(socket).on("file", function(stream, data) {
var filename = path.basename(data.name);
var parts = [];
stream.on("data", function(data) {
parts.push(data);
});
stream.on("end", function() {
socket.broadcast.emit("file", parts);
});
});
});
server.listen(8080, function () {
console.log("Listening on 8080")
});
This is my client.js file:
// Browserified
var P2P = require("socket.io-p2p");
var io = require("socket.io-client");
var ss = require("socket.io-stream");
var socket = io();
var opts = {autoUpgrade: true, peerOpts: {numClients: 10}};
var p2p = new P2P(socket, opts);
var $ = require("jquery");
p2p.on("peer-num", function(num) {
console.log("You are peer number " + num);
$(".peerNum").html( "Number " + num );
});
p2p.on("file", function(stream) {
console.log(stream);
var img = document.createElement("img");
img.src = (window.URL || window.webkitURL).createObjectURL(new Blob(stream));
document.getElementById("receivedImages").appendChild(img);
});
$(function() {
$("#file").change(function(e) {
ss.forceBase64 = true;
var file = e.target.files[0];
var stream = ss.createStream();
ss(socket).emit("file", stream, {size: file.size,name:file.name});
var blobStream = ss.createBlobReadStream(file);
var size = 0;
blobStream.on("data", function(chunk) {
size += chunk.length;
console.log(Math.floor(size / file.size * 100) + "%");
});
blobStream.pipe(stream);
});
});
If what you mean by id is the internal id that socket.io assigns to a connection (on the server), then you can access that with socket.id. So, if you want to just use socket.id instead of your peerNum, variable, then you would change this:
io.emit("peer-num", peerNum);
to this:
io.emit("peer-num", socket.id);
The socket.id value is used only on the server. It is not meant to be a human readable moniker (it contains randomly generated characters), but it can be used to reference any given connection. Since its a string, it can be easily sent to other clients who can then use it when sending messages back to the server to reference particular client connections.
I'm currently working on a Phonegap app, and I would like users to be able to upload any file to my NodeJS server.
I've looking all around the web but I just can't get anything to work...
Here is the code I'm using for the Phonegap controller:
$scope.open = function()
{
navigator.camera.getPicture(upload,
function(message)
{
alert('get picture failed');
},
{
quality: 50,
destinationType: navigator.camera.PictureSourceType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
mediaType: navigator.camera.MediaType.ALLMEDIA
});
}
var win = function (r) {
$scope.log = "Code = " + r.responseCode;
$scope.log2 = "Response = " + r.response;
$scope.log3 = "Sent = " + r.bytesSent;
$scope.$digest();
}
var fail = function (error) {
$scope.log = "An error has occurred: Code = " + error.code;
$scope.log2 = "upload error source " + error.source;
$scope.log3 = "upload error target " + error.target;
$scope.$digest();
}
function upload(fileURI)
{
$scope.log = fileURI;
$scope.$digest();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
options.chunkedMode = false;
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(fileURI, "http://192.168.192.111:2999/upload", win, fail, options);
}.
Here is the current code for the NodeJS server, have tried a lot of different things, all without success:
var express = require('express');
var http = require('http').Server(express);
var io = require('socket.io')(http);
var fs = require('fs');
var multer = require('multer');
var app = new express();
app.post('/upload', multer({dest: './uploads/'}).single('upl'), function(req, res)
{
console.log(req.body);
console.log(req.file);
})
http.listen(2999, function(){
console.log('listening on *:2999');
});
In the app I used to get errors that FileUploadOptions etc weren't defined, but I fixed that by adding them to the cordova project.
Furthermore, I use ionic 1, if that helps anyone out.
I do keep constantly getting the error code 1 (upload error source), even though I selected a real file and I saw that the link was correct (something like /storage/0/emulated/Downloads on my Android device).
Also, sometimes it gives me error 3 as well (upload target source), some sort of server not found issue I think.
Is there something obvious I'm doing wrong and how would I be able to fix it? Is there a handier way, since I eventually want to link this to a MySQL database.
Thanks in advance!
Well found my answer (a while ago, this is for people stumbling across this post).
You can first try whether your JS works by changing the server to https://posttestserver.com/post.php. If you see an upload appearing there, there's a problem with the server.
The problem with me was that I didn't let Apache through the firewall at all, so uploads from anything besides my PC would fail...
var express=require('express');
var bodyParser=require('body-parser');
var formidable = require('formidable');
var util = require('util');
var app=express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var path=require('path');
var mysql =require('mysql');
var fs=require('fs');
app.use('/public',express.static(path.join(__dirname, 'public')));
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password : '',
port : 3306, //port mysql
database:'xxxxx'
});
app.post('/data', function(req, res) {
// create an incoming form object
var form = new formidable.IncomingForm(),
files = [],
fields = [];
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/public/images/uploads');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
if (path.extname(file.name)=='') {
extension='.jpg';
}
else{
extension=path.extname(file.name);
}
var oldpath = file.path;
form.uploadDir = path.basename(file.name,extension).concat((Math.random()* 100),extension);
var newpath = './public/images/uploads/'+ path.basename(file.name,extension).concat((Math.random()* 100),extension);
//fs.rename(file.path, path.join(form.uploadDir, file.name));
fs.rename(oldpath, newpath);
});
form.on('field', function(field, value) {
fields[field] = value;
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
//Call back at the end of the form.
form.on('end', function () {
res.writeHead(200, {
'content-type': 'text/plain'
});
res.write('received the data:\n\n');
// console.log(fields.name+'-'+fields.nickname);
var values={
name:fields.name,
nickname:fields.nickname,
email:fields.email,
password:fields.password,
dob:fields.dob,
gender:fields.gender,
phoneno:fields.phone
};
connection.query('INSERT INTO users SET ?', values, function(err,req,res){
if(err){
console.log('Connection result error '+err);
}
else{
console.log('Success');
}
});
res.end();
});
// parse the incoming request containing the form data
form.parse(req);
});
//app.use(app.router);
app.listen(5000);
I've been stumped on this for a while now, no matter the configuration if use in NodeJS I always get the same error "Error: ffmpeg exited with code 1".
Here's my code:
var http = require('http');
var fs = require('fs');
var ffmpeg = require('fluent-ffmpeg');
var server = http.createServer(function(req, res) {
var seektime = 100;
var pathToMovie = __dirname + '/src/video.mp4';
var stat = fs.statSync(pathToMovie);
res.writeHead(200, {
'Content-Type': 'video/mp4',
'Content-Length': stat.size
});
var proc = new ffmpeg(pathToMovie)
.seekInput(seektime)
.withVideoBitrate(1024)
.withVideoCodec('libx264')
.withAspect('16:9')
.withFps(24)
.toFormat('mp4');
var ffstream = proc.pipe(res, {end:true});
ffstream.on('data', function(chunk) {
console.log('ffmpeg just wrote ' + chunk.length + ' bytes');
});
});
server.listen(8000);
I have no idea what to do now. Any ideas?
Thanks,
Jamie
I am using express and nodejs and am having problems saving facebook profile pictures to my server.
Location of picture: http://profile.ak.fbcdn.net/hprofile-ak-ash2/275619_223605264_963427746_n.jpg
Script Being Used:
var http = require('http')
var fs = require('fs')
var options = {
host: 'http://profile.ak.fbcdn.net',
port: 80,
path: '/hprofile-ak-ash2/275619_223605264_963427746_n.jpg'
}
var request = http.get(options, function(res){
res.setEncoding('binary')
var imagedata = ''
res.on('data', function (chunk) {imagedata += chunk})
res.on('end', function(){
fs.writeFile('logo.jpg', imagedata, 'binary', function (err) {
if(err){throw err}
console.log('It\'s saved!');
})
})
})
The image saves but is empty. Console logging the image data is blank too. I followed this example origionally which does work for me. Just changing the location of the image to the facebook pic breaks the script.
I ended up coming up with a function that worked:
var http = require('http');
var fs = require('fs');
var url = require('url');
var getImg = function(o, cb){
var port = o.port || 80,
url = url.parse(o.url);
var options = {
host: url.hostname,
port: port,
path: url.pathname
};
http.get(options, function(res) {
console.log("Got response: " + res.statusCode);
res.setEncoding('binary')
var imagedata = ''
res.on('data', function(chunk){
imagedata+= chunk;
});
res.on('end', function(){
fs.writeFile(o.dest, imagedata, 'binary', cb);
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
}
USAGE:
getImg({
url: "http://UrlToImage.com",
dest: __dirname + '/your/path/to/save/imageName.jpg'
},function(err){
console.log('image saved!')
})
I know my answer is a little late, but I hope it'll help others we get to this question, so here it is:
Saving the file to the root directory of your Node server can be done this way:
var request = require("request");
var fs = require("fs");
var fbUserId = 4;
var imageLink = "https://graph.facebook.com/"+ fbUserId +"/picture?width=500&height=500";
request(imageLink).pipe(fs.createWriteStream("resultIMG.png"))
.on('close', function(){
console.log("saving process is done!");
});
Of course, you can add any path you want for the image prior the the file name string.
If you still are seeing empty images, set the encoding of the request module to null , like this:
var request = require("request").defaults({ encoding: null });
That should do it.