nodejs send mp3 from another server to the client - node.js

I have an express server it grabs stuff from my other server, edits it, and sends it to the client using the curl library (I tried request but it did the same thing). Everything works great except when I try sneding an MP3 file. If I try that then Chrome can't decode the MP3. However, If I access the MP3 from the original server it decodes fine and plays. I don't edit the MP3's. Here is what my code looks like:
// server2.example.com source
const curl = require("curl");
const edit = (b, p) => {};
const express = require("express");
/* ... express app stuff ... */
app.get("*", (req, res) => {
curl.get(
"http://server1.example.com" + req.path, {},
(err, response, body) => {
if (err) return;
res.type(response.headers["content-type"]).status(response.statusCode).send(edit(body, patches));
}
);
});
app.listen(80);
Once again the file is un-edited and the exact same file as the one on server1. Here is a screenshot of what I see when visiting server1.example.com/audio.mp3 versus server2.example.com/audio.mp3:
server2.example.com/audio.mp3 screenshot
server1.example.com/audio.mp3 screenshot

Related

How to upload file from nodeJS to nodeJS

I have 2 nodeJS services and I would want to upload file in a dir, from one NodeJS (backend) to another NodeJS(backend). The receiver nodeJS is an express app.
Looking for some working code sample.
PS: Couldn't find any code samples in search, since everywhere it was Multer from client to server uploads that receives multipart/form-data.
Uploading file using POST request in Node.js
Receive the file first as you correctly said using Multer. Then, you may either save the file to a temporary directory before uploading it again or just send the file as-is.
You need to setup a server running with Multer on the 2nd server that wishes to receive the file.
const express = require('express');
const app = express();
const upload = multer({ dest: 'files/' });
app.post('/upload', upload.single('file'), (req, res) => {
res.sendStatus(200);
});
app.listen(3001);
Then on the server you wish to send the file from, do something like this:
const request = require('request');
const req = request.post('localhost:3001/upload', (err, res, body) => {
if (err) throw new Error(err);
if (res && res.statusCode == 200) {
console.log('Success');
} else {
console.log('Error');
};
});
const form = req.form();
form.append('file', fs.createReadStream('./location/to/file'));

How to make an express page that contains all my front-end js scripts?

I'm trying to make a root where there's all my front end scripts.
So when I want to import my scripts in my index.html I just need to do :
<script src="/front/scripts"></script>
First problem :
This is my server code :
app.use('/front/scripts', (req, res) => {
const readScript = (filePath) => {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err) throw err;
return res.write(data);
});
};
readScript('./node_modules/jquery/dist/jquery.js');
readScript('./node_modules/socket.io-client/dist/socket.io.js');
readScript('./src/js/app.js');
});
It's not working because express is keep loading the page so I can't import it because my index.html is waiting for my front/scripts to stop loading.
Second problem:
It will not work because of the size of the file, the lightest file will be loaded faster than a bigger one like jQuery, so the lightest file will be at the top of front/scripts and the big one will be after le lightest.
For example if my personal app.js is just a 3 lines jQuery script that change the content of a div, it will return me an error because my script is loaded before jQuery.
How can I do this properly?
Once all scripts have been read and written to response finally the response must get finalized as well using res.end();
Example below has a small change as the readFile is async so there's no guarantee that res.end() is called at the right time. Made it synced.
See here fs.readFileSync.
app.use('/front/scripts', (req, res) => {
const readScript = (filePath) => {
res.write(fs.readFileSync(filePath, 'utf-8'));
};
readScript('./node_modules/jquery/dist/jquery.js');
readScript('./node_modules/socket.io-client/dist/socket.io.js');
readScript('./src/js/app.js');
res.end();
});
Use express.static
Example:
Sample project setup:
server.js
front
scripts
app.js
server.js:
const express = require('express')
const { join } = require('path')
const app = express()
app.use(express.static(join(__dirname, 'front/scripts'))
app.listen(3000)
You'll get your app.js here: localhost:3000/app.js

nodejs pipe https response to request.post and write file

I am Making http proxy program that check http url and If It is download link(content-type:octet-stream), I would get response and relay that response to other computer by using request.post and other computer download file with response that are given by http proxy.
Let's suppose that web proxy computer is A. And It is part of code of A. 192.168.5.253
if(contentType && (contentType== "application/octet-stream" || contentType == "application/gzip")){
console.log("remoteRes##app",remoteRes);
let filepath = req.url.split('/');
let FileName = getFilename(remoteRes, filepath);
let writeStream = fs.createWriteStream(FileName);
/*remoteRes is octect-stream response.
I can get file buffer If I use remoteRes.on(data, chunk => {...})*/
remoteRes.pipe(writeStream); //It works but I want to send file buffer to B without writing file.
.........
I can download file in A. but I want to send this response to pc B(192.168.5.32:10001) server.
So I want to streaming like this:
remoteRes.pipe(request.post('http://192.168.5.32:10001/upload));
And this is part of Server B(192.168.5.32) code
router.post('/upload', (req, res, next) => {
let wstream = fs.createWriteStream('ffff.txt');
req.pipe(wstream); //It dosen't work, but I want to do like this.
})
I want to get filebuffer in router.post('/upload'). It dosen't matter If It is post or put.
I saw that when I use remoteRes.pipe(request.post('http://192.168.5.32:10001/upload));
,I saw that request from ServerA get to ServerB. But I couldn't get file buffer in ServerB.
In short, I want to pipe response to request.post.
You need to store the incoming buffers using your own middleware, so it will be available in the routers request handler
Here you have a working example (you can save it and test it as a single file) :
//[SERVER B]
const express = require('express'); const app = express()
//:Middleware for the incoming stream
app.use(function(req, res, next) {
console.log("[request middleware] (buffer storing)")
req.rawBody = ''
req.on('data', function(chunk) {
req.rawBody += chunk
console.log(chunk) // here you got the incoming buffers
})
req.on('end', function(){next()})
});
//:Final stream handling inside the request
app.post('/*', function (req, res) {
/* here you got the complete stream */
console.log("[request.rawBody]\n",req.rawBody)
});
app.listen(3000)
//[SERVER A]
const request = require('request')
request('http://google.com/doodle.png').pipe(request.post('http://localhost:3000/'))
I hope you can extrapolate this for your specific use case.

Download a youtube video file in node js using ytdl

I want to make user able to download a youtube video using node-ytdl.
For example when client side make a GET request for certain route the video should be downloaded in response.
var ytdl = require('ytdl-core');
var express= require('express');
//Init App Instance
var app=express();
app.get('/video',function(req,res){
var ytstream=ytdl("https://www.youtube.com/watch?v=hgvuvdyzYFc");
ytstream.on('data',function(data){
res.write(data);
})
ytstream.on('end',function(data){
res.send();
})
})
Above is my nodejs code. Even though in network it seems to download the response it does not make user download as a file.I don't want to store any file on server.It would be great if someone could help me how to solve the issue.
res object is a writable stream so you can directly pipe the output of ytdl to res object like this -
ytdl("http://www.youtube.com/watch?v=xzjxhskd")
.on("response", response => {
// If you want to set size of file in header
res.setHeader("content-length", response.headers["content-length"]);
})
.pipe(res);
You have to also pass the headers. Try it:
app.get('/video', (req, res) => {
var url = "https://www.youtube.com/watch?v=hgvuvdyzYFc";
res.header("Content-Disposition", 'attachment; filename="Video.mp4');
ytdl(url, {format: 'mp4'}).pipe(res);
});
If someone is still getting an error just update the package to latest version by running:
npm i ytdl-core#latest
Ok, so make a string var, then add data to it on the data event. On end, send everything. Here is an example:
const ytdl = require("ytdl-core"),
app = require("express")();
app.get("/video", (req, res) => {
let data = "", vid = ytdl("https://www.youtube.com/watch?v=hgvuvdyzYFc");
vid.on("data", d => data += d);
vid.on("end", () => res.send(data));
res.header("Content-Disposition", 'attachment; filename="Video.mp4');
});

NodeJS + FFMPEG -sending response when FFMPEG is completed

I have a working NodeJS+FFMPEG application. I am able to upload video files and have them converted on the server. I am using this NodeJS FFMPEG library
https://github.com/fluent-ffmpeg/node-fluent-ffmpeg
I get a message on the server when the job is complete, but how do I notify the client?? In this case a simple AIR application. Right now I can only 'hear' the initial response after a successful upload.
The initial video file was uploaded via a http POST request.
My primary node application without the dependencies is as follows
var ffmpeg = require('./lib/fluent-ffmpeg');
var express = require('express'),
multer = require('multer');
var app = express();
//auto save file to uploads folder
app.use(multer({ dest: './uploads/'}))
var temp;
app.post('/', function (req, res) {
console.log(req.body); //contains the variables
console.log("req.files ="+ req.files); //contains the file references
console.log("req.files.Filedata.path ="+ req.files.Filedata.path );
temp=req.files.Filedata.path;
// make sure you set the correct path to your video file
var proc = ffmpeg('./'+temp)
// set video bitrate
.videoBitrate(1024)
// set audio codec
.audioCodec('libmp3lame')
// set output format to force
.format('avi')
// 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 file
.save('./converted/converted.avi');
res.send('Thank you for uploading!');
});
app.listen(8080);
There are two approaches you can use. The first is to poll the server from the client with AJAX GET requests every x seconds. The second approach is to use WebSockets and notify the client by sending a message to them directly.

Resources