javaTest
javaTest

Reputation: 15

How to copy data from one stream to another in Node JS

I want to copy data from one stream to another in Java i do in below way

ByteStreams.copy( inputStream, outputStream );

In Node JS i am trying to find out how to do that

    // Making an ajax call to get the Video file
const getVideo = async (req, res) => {
  try {
      axios.get('Video URL')
          .then(function (videoResponse) {
              res.setHeader("Content-Type", "video/mp4");
              // copy the inputStram of videoResponse 
              //to the output stram of res
              // copy the videoResponse to res
          })
  } catch (error) {
      console.log(error);
  }
};

Can anyone suggest how to do that, Thank you for your help

Upvotes: 0

Views: 2430

Answers (3)

Daemon Beast
Daemon Beast

Reputation: 2909

You need to set the responseType from axios to 'stream', then you can pipe data from the input stream to the response stream using .pipe().

// Making an ajax call to get the video file
const getVideo = async (req, res) => {
  try {
    axios({
      method: 'get',
      url: 'Video URL',
      responseType: 'stream'
    }).then((videoResponse) => {
      res.setHeader("Content-Type", "video/mp4");

      videoResponse.data.pipe(res);
    });
  } catch (err) {
    console.log(err);
  }
}

For more information about the .pipe() function, please read the Node.js docs.

For more information about axios request configuration options, please read the axios docs.

Upvotes: 2

Daniele Dellafiore
Daniele Dellafiore

Reputation: 1897

The most simple example for reading and writing to File System would be:

  const fs = require('fs')
  const input = fs.createReadStream('input_file')
  const output = fs.createWriteStream('output_file')
  input.pipe(output)

Check the File System docs for Node.js.

The input and output stream can be any ReadStream and WriteStream, like an HTTP response or S3 for example.

From the Axios Github README you have the example which looks very similar to what you are trying to do (please use the original one, I had to change the URL here)

// GET request for remote image in node.js
axios({
  method: 'get',
  url: 'https://lh3.googleusercontent.com/iXm....',
  responseType: 'stream'
})
  .then(function (response) {
    response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
  });

Upvotes: 1

Sohan
Sohan

Reputation: 6809

The example below streams video outpu. I am assuming you need something similar. Can you try something like this and based on this example modify your code

const express = require('express')
const fs = require('fs')
const path = require('path')
const app = express()
 
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'))
})
 
app.get('/video', function(req, res) {
const path = 'assets/sample.mp4' //This can be replaced by axios.get('Video URL')
const stat = fs.statSync(path)
const fileSize = stat.size
const range = req.headers.range
 
if (range) {
const parts = range.replace(/bytes=/, "").split("-")
const start = parseInt(parts[0], 10)
const end = parts[1]
? parseInt(parts[1], 10)
: fileSize-1
 
const chunksize = (end-start)+1
const file = fs.createReadStream(path, {start, end})
const head = {
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4',
}
 
res.writeHead(206, head)
file.pipe(res)
} else {
const head = {
'Content-Length': fileSize,
'Content-Type': 'video/mp4',
}
res.writeHead(200, head)
fs.createReadStream(path).pipe(res)
}
})
 
app.listen(3000, function () {
console.log('App is running on port 3000')

In the above code:

At the top I have included needed NPM packages. After that we have a get method served on route '/' for serving the html file. Then there is a get method with route '/video' which is being called from html file. In this method at first the filesize is detected with statSync method of fs. after that with stream video is downloaded to client in chunks. With every new request from client the value of start and end is changing to get the next chunk of video. 206 is set in response header to send only newly made stream(chunk of video).

Credit - Example source

Upvotes: 0

Related Questions