33

I would like to read a remote image and display it. I can save the file but not getting the code right to display it. Ideally I just want to pass the file right though without processing - not sure if a tmp file step is required or not. This code displays nothing - no errors. I tried res.pipe(response) as well.

var url = 'http://proxy.boxresizer.com/convert?resize=50x50&source=' + filename

var request = http.get(url, function(response) {

  var tmp = path.join(require('os').tmpDir(), filename);

  var outstream = require('fs').createWriteStream(tmp);

  response.pipe(outstream);
  response.on('end', function() {
    res.set('Content-Type', 'image/jpg');
      res.pipe(outstream);
      res.end();
  });
});
cyberwombat
  • 38,105
  • 35
  • 175
  • 251

3 Answers3

38

Well I'd still like to know how to make the above work but I solved my issue in one line with the request module!

var url = 'http://proxy.boxresizer.com/convert?resize=50x50&source=' + filename
require('request').get(url).pipe(res);  // res being Express response
cyberwombat
  • 38,105
  • 35
  • 175
  • 251
  • 4
    This is much better. You are not saving the file on disk. If you want to save the response, after `response.pipe(outstream);` you have to reopen the file with `createreadstream` and pipe it to `res`. In the question you did `res.pipe(outstream);` which is a mistake. You have to pipe file to `res`. – user568109 Aug 26 '13 at 06:12
  • 1
    could you please share the whole code? Do you still need to end the response or any additional action? – Eric Burel Aug 26 '20 at 07:13
11

Since request is deprecated, you can alternatively use node-fetch like so:

app.get("/", (req, res) => {
    fetch(actualUrl).then(actual => {
        actual.headers.forEach((v, n) => res.setHeader(n, v));
        actual.body.pipe(res);
    });
});
ABabin
  • 2,724
  • 24
  • 30
  • Hmm, it doesn't work for me, or at least, Typescript gives an error that there's no pipe() method. I tried pipeTo() instead but its argument is a WritableStream not a Response object like res. – Bill Keese Feb 22 '23 at 05:43
  • Seems to be working okay [here](https://stackblitz.com/edit/node-meea3q?file=app.ts&view=editor). `actual.body` may be null so a nullish coalescing operator before the call to `pipe` may be needed, depending on your TS config. – ABabin Feb 23 '23 at 16:33
  • You're right, it does work when using node-fetch, but only because node-fetch deviates from the fetch() standard. It's documented in https://github.com/node-fetch/node-fetch#bodybody. The standard method is pipeTo() not pipe() but it's not a 1-1 replacement. – Bill Keese Feb 24 '23 at 01:00
  • Yeah, node has its own stream API that predates Web Streams, and that's what `node-fetch` is using. Node introduced it's own implementation of `fetch` in v17.5 and it's browser compatible. It's a [global](https://nodejs.org/docs/latest-v18.x/api/globals.html#fetch) since v18. – ABabin Feb 24 '23 at 18:11
3

This is what seems to work for me, using the standard fetch() included in Node 18, which is a bit different than node-fetch, see github.com/node-fetch/node-fetch#bodybody:

app.get("/", (req, res) => {
  fetch(url).then((response) => {
    body.pipeTo(
      new WritableStream({
        start() {
          response.headers.forEach((v, n) => res.setHeader(n, v));
        },
        write(chunk) {
          res.write(chunk);
        },
        close() {
          res.end();
        },
      })
    );
  });
});

Bill Keese
  • 1,792
  • 14
  • 29