0

My nodejs backend is running on localhost:8080 and frontend on localhost:8081 using http-server, I am not able to download file from my server side to client side, I am new to node js so facing some problems with it

What I tried

I created a readstream to my required file on server side and then pipe it to res object , also I set some headers :-

res.setHeader("Content-Type","image/png") // as I am trying to download a 
res.setHeader("Content-Disposition", `inline; filename=${filename}`);

But it still fails

Code:-

code for downloading a file from server side

let filename = "hello.png";
let readStream = fs.createReadStream(path.join(__dirname, "..", chatDoc.chatContent));
res.setHeader("Content-Type", "image/png")
res.setHeader("Content-Disposition", `inline; filename=${filename}`);
readStream.pipe(res);

cors code:-

const cors = require("cors");
app.use(cors({
    origin: "http://localhost:8081",
    credentials: true,
    withCredentials: true
}))

frontend code:-

fetch("http://localhost:8080/downloadNow",{
    method:"POST",
    headers:{
      "Content-Type":"application/json"
    },
    body:JSON.stringify({
      chatId:chatId
    }),
    credentials:"include"
  })
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  })

Response on frontend:- I got successfully response from server but file isn't downloaded.

enter image description here

please help me out with this

BHANU ARORA
  • 81
  • 1
  • 8

2 Answers2

1

Is that all of your servercode handling the download? If yes, you are not waiting for the readStream to properly open. And you should also add proper error handling, when the readStream couldn't be opened. Use

let readStream = fs.createReadStream(path.join(__dirname, "..", chatDoc.chatContent));
readStream.on("open", () => {
  res.setHeader("Content-Type","image/png")
  res.setHeader("Content-Disposition", `inline; filename=${filename}`);
  readStream.pipe(res);
})
readStream.on("error", e => {
  console.log(e);
  res.writeHead(400);
});

And to download a file with fetch(in my understanding this means saving the file to disk instead of displaying it in the browser) you nonetheless need to apply the means of the referenced question ...

derpirscher
  • 14,418
  • 3
  • 18
  • 35
  • thanks, my code worked now , but there is a small problem with your server side code you should write readstream.pipe(res), edit it and then I will mark this as correct – BHANU ARORA Jul 28 '21 at 10:13
  • @BHANUARORA Yes, you are right. I swapped that in a hurry ... – derpirscher Jul 28 '21 at 10:15
0

Try this one

Server

let mime = {
  html: 'text/html',
  txt: 'text/plain',
  css: 'text/css',
  gif: 'image/gif',
  jpg: 'image/jpeg',
  png: 'image/png',
  svg: 'image/svg+xml',
  js: 'application/javascript'
};
app.post('/imageDownload', async(req, res) => {
  var type = mime[path.extname(req.body.imagePath).slice(1)] || 
  'text/plain';
  var s = fs.createReadStream(file);
  s.on('open', function () {
   res.set('Content-Type', type);
   s.pipe(res);
  });
  s.on('error', function (err) {
   console.log(err)
   res.send(err)
  });
}

Client

fetch(`/imageDownload`,{ 
   method: 'POST',
   headers:{
        "Content-Type":"application/json"
   },
   body:JSON.stringify({
      imagePath:url
   }),
 }).then(response => response.blob())
   .then(function(myBlob) {
        const url = window.URL.createObjectURL(new Blob([myBlob]));
         const link = document.createElement('a');
         link.href = url;
         link.setAttribute('download', "filename.jpg"); 
         document.body.appendChild(link);
         link.click();
  })
Ramesh L
  • 59
  • 4
  • That looks to be the same as [this answer](https://stackoverflow.com/a/42274086/19068) which the OP said did not solve their problem. – Quentin Jul 28 '21 at 09:53