0

I have a GET route in express that should return a binary png image stored in mongodb. However, when I enter the url into chrome to test, the image is downloaded but the request never completes. From the Network tab in Chrome DevTools the request is just stuck in the 'pending' state. I'm only getting this problem with binary data it seems. I have plenty of other json GET requests that work just fine with send().

I am using the send() function like this:

exports.getProjectPng = (req, res) => {
  Project.findById(req.params.projectId).select('project.png')
    .then(project => {    
      res.send(project.png.buffer);
  });

If I simply replace send() with end() the request completes as expected. Also, perhaps significantly, the png image is actually rendered within the browser rather than downloading as a file.

So why does end() work but send() doesn't?

2 Answers 2

1

If you point curl at an express server and see what the response looks like for both methods it is quite interesting. The main difference is what when we call send, the Content-Type header is populated, which is consistent with the Express docs:

When the parameter is a Buffer object, the method sets the Content-Type response header field to “application/octet-stream”, unless previously defined

It's worthwhile noting that res.send() actually calls res.end() internally at the end of the call, so the different behaviour is likely down to something that res.send does in addition to res.end.

It might be worth populating the Content-Type Header in your example to "image/png" before sending.

e.g.

res.set('Content-Type', 'image/png');

For .end():

* Connected to localhost (::1) port 8081 (#0)
> GET /downloadpng_end HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8081
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Date: Mon, 25 Jun 2018 13:14:58 GMT
< Connection: keep-alive
< Content-Length: 69040
<

And for send():

* Connected to localhost (::1) port 8081 (#0)
> GET /downloadpng_send HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8081
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/octet-stream
< Content-Length: 69040
< ETag: W/"10db0-KwFSGG5Ib/DQNZChAbluTiKSP0o"
< Date: Mon, 25 Jun 2018 13:15:25 GMT
< Connection: keep-alive
<
Sign up to request clarification or add additional context in comments.

2 Comments

res.set('Content-Type', 'image/png'); fixes the problem for me. The odd behaviour I was getting seems to be a combination of Chrome and application/octet-stream content-type.
Cool! I kinda suspected a bit of browser-specific behaviour here. I was testing in Firefox as well, and I didn't see exactly the same behaviour
-1

Nodejs does not handle straight binary data very well.So , thats what buffer is used to handle binary data.

End() Method

end − This event is fired when there is no more data to read. while send has no guarantee whether its completed or not. You can read more about Buffer on offical docs here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.