Node Express sending image files as API response

157,845

Solution 1

There is an api in Express.

res.sendFile

app.get('/report/:chart_id/:user_id', function (req, res) {
    // res.sendFile(filepath);
});

http://expressjs.com/en/api.html#res.sendFile

Solution 2

a proper solution with streams and error handling is below:

const fs = require('fs')
const stream = require('stream')

app.get('/report/:chart_id/:user_id',(req, res) => {
  const r = fs.createReadStream('path to file') // or any other way to get a readable stream
  const ps = new stream.PassThrough() // <---- this makes a trick with stream error handling
  stream.pipeline(
   r,
   ps, // <---- this makes a trick with stream error handling
   (err) => {
    if (err) {
      console.log(err) // No such file or any other kind of error
      return res.sendStatus(400); 
    }
  })
  ps.pipe(res) // <---- this makes a trick with stream error handling
})

with Node older then 10 you will need to use pump instead of pipeline.

Share:
157,845

Related videos on Youtube

metalaureate
Author by

metalaureate

Professional product manager, amateur hacker. I'm constantly amazed by the generosity and quality of StackOverflow members. Thank you! I take far more than I give, and am constantly in your debt.

Updated on July 08, 2022

Comments

  • metalaureate
    metalaureate almost 2 years

    I Googled this but couldn't find an answer but it must be a common problem. This is the same question as Node request (read image stream - pipe back to response), which is unanswered.

    How do I send an image file as an Express .send() response? I need to map RESTful urls to images - but how do I send the binary file with the right headers? E.g.,

    <img src='/report/378334e22/e33423222' />
    

    Calls...

    app.get('/report/:chart_id/:user_id', function (req, res) {
         //authenticate user_id, get chart_id obfuscated url
         //send image binary with correct headers
    });
    
    • 7zark7
      7zark7 almost 11 years
      How do you retrieve the image server side?
  • BRogers
    BRogers over 9 years
    instead of a file path could you do it from a stream? for instance if you had a variable that you were storing a file in so that you didn't have to actually save the file on the server?
  • Po-Ying Chen
    Po-Ying Chen over 9 years
    @BRogers res is a writable stream, so if you have a Buffer object or a string then you can use .write method to send it to client.
  • BRogers
    BRogers over 9 years
    Thank you, I will be trying this. I have a CSV buffer that I want to send back to the client and it show as a downloaded file. I'll have to toy with that one. The file isn't very big, so I'm hoping to accomplish this.
  • BRogers
    BRogers over 9 years
    That worked beautifully! Just had to remember to set the Content-Type. Thank you!
  • Jason Shultz
    Jason Shultz almost 9 years
    res.sendfile is deprecated now, the preferred method is res.sendFile: expressjs.com/api.html#res.sendFile
  • Rajesh
    Rajesh over 8 years
    @BRogers or anybody: Can you pls help me with the writable stream code if you have ? i'm looking for help on downloading different formats(jpg, xls and etc). i've posted my question in forum as well stackoverflow.com/questions/34588839/…. But no luck !!!
  • Harry
    Harry about 7 years
    Crucially, it has to be an absolute file path, otherwise you get a (in this context) cryptic Error: No default engine was specified and no extension was provided.
  • Admin
    Admin almost 5 years
    What if you had multiple images? I'm a little hesitant to use Base64 Encoding.