1

I'm currently trying to copy the content of a file into another one using Node.js through the fs.createWriteStream and fs.createReadStream functions.

To be more specific, the file is a music sample that I would like to duplicate. Also, I expect the resulting file to be readable by a player like any music or video. It's this last point that I don't manage to perform. The files are indeed duplicated, but the the resulting file is not accepted by my player as a readable file, like if it was corrupted somehow.

I checked its content and there it doesn't seem to be a matter a programmation logic, as the the datas of the original file have been correctly transposed into the copy. Here is my script, if you want to take a look.

const express = require('express')
const app = express()
const fs = require("fs")
var Promise = require("bluebird")
Promise.promisifyAll(fs)

const path = require('path')
const file1 = path.join(__dirname, 'sample1.wav') // The file to copy
const file2 = path.join(__dirname, 'sample2.wav') // The destination of the new file

app.use(async(req,res,next)=>{

  let file1_stream = await fs.createReadStream(file1)
  let file2_stream = await fs.createWriteStream(file2)
  file2_stream.pipe(file2_stream)
  next()

})

.listen(8080)

I guess the operation is not as simple as just copying a stream and inject it with a pipe like shown above. if someone has any idea what I am missing here, I am all ears. Thanks by advance.

1 Answers1

1

That code is triggering an error, which you're probably not handling correctly, since you're using an async middleware on express.

 Error [ERR_STREAM_CANNOT_PIPE]: Cannot pipe, not readable

You have to use .pipe on the readableStream not on the writeableStream

So the code should be:

file1_stream.pipe(file2_stream);

Also, you don't need to await on fs.createWriteStream. It's doing nothing. The promisify works on callbacks APIs, but createWriteStream & createReadStream don't take a callback as an argument.

app.use((req,res,next)=>{

  let readStream = fs.createReadStream(file1);
  let writeStream = fs.createWriteStream(file2);
  readStream.pipe(writeStream);

  // Call next once the file was actually copied
  writeStream.on('finish', next);

  writeStream.on('error', next); // go to express error handler
  readStream.on('error', next);

});
Marcos Casagrande
  • 37,983
  • 8
  • 84
  • 98
  • 1
    What can I say? It works like a charm. I don't know why I tried to async all the process, that was nonsense. thanks a lot for your answer and your very concise explanations. – FitzChevalerie Mar 09 '19 at 20:04
  • Glad it worked!. If you want to learn about express & async middlewares, you can check this answer of mine: https://stackoverflow.com/questions/51391080/handling-errors-in-express-async-middleware/51391081#51391081 – Marcos Casagrande Mar 09 '19 at 20:09