1

I've been writing a web app for some time now, and I've been running into some issues with serving images.

My code pulls file data from the server, using file_get_contents, and uses Slim's Request object's write method to output the contents of the file, setting the headers as it goes. For most files, this works, however larger images often only show a gray outline of the image dimensions (tested in mobile and desktop Chrome). Requests error out with ERR_SPDY_PROTOCOL_ERROR, which led me to believe it was an HTTP 2 issue (the server I test on listens for HTTP 2 connections, set with the listen [port] http2 directive in its nginx config), however I attempted to downgrade the HTTP version used in the response with PSR-7's RequestInterface's withProtocolVersion method and nothing changed.

I know using file_get_contents then outputting said contents is a very roundabout way to do things, but it's the only way I know to allow users of this app to arbitrarily set the location of uploaded files.

This is the most relevant part of my code, where $filepath is the path to the file the user requested. This code works as expected for all files except for large images.

return $response->withHeader('Content-Type', mime_content_type($filepath))->write(file_get_contents($filepath));
Bytewave
  • 597
  • 1
  • 8
  • 20
  • You say 'half the time' ... That would seem as though there is 2 servers being load balanced? One of them may not have the file? ... Do you know the infrastructure your app is running on? – Just Lucky Really Sep 25 '16 at 01:07
  • @Stretch I should have been more specific—my apologies. It's a random chance, however very unlikely, that it loads. My app runs on a single nginx server, so only one instance and no load balancing. – Bytewave Sep 25 '16 at 01:09
  • Ah okay ... So is the issue only confined to larger files? ... I did have an issue in the past with serving large downloadable files (Not streaming), and solved it using the Nginx `sendfile` ... https://www.nginx.com/resources/admin-guide/serving-static-content/ – Just Lucky Really Sep 25 '16 at 01:15
  • It's possible that your configuration is trying to cache files as they are requested. And with large files that can become a problem. – Just Lucky Really Sep 25 '16 at 01:16
  • Does nginx cache content generated by PHP? That could be the issue. The issue does seem to be isolated to large files, but the only "large images" I've tested are from Android phone cameras (doubting that makes a difference). – Bytewave Sep 25 '16 at 01:19
  • 1
    Ah sorry I think I skipped over the part where you said you was using `file_get_contents()` to serve files ... Using `file_get_contents()` will load it into memory. Hopefully you can see the problem with that :D – Just Lucky Really Sep 25 '16 at 01:29
  • There are very limited cases where you would need to use `file_get_contents()` to present the file to a user. I think it would be best to rethink your strategy. – Just Lucky Really Sep 25 '16 at 01:32
  • @Stretch The problem with not using `file_get_contents` is that some files are safeguarded by requiring logins to view. While I could place files in the `/public/` directory and pull them in through the client, I'm not sure how I would go about protecting files that users shouldn't be able to see. – Bytewave Sep 25 '16 at 03:38
  • The site **does** run with a MySQL database attached, and I've considered the idea of storing the files as BLOBs, but that would require quite a bit of restructuring, and I'm not sure what the performance metrics are like for BLOBs. – Bytewave Sep 25 '16 at 03:39
  • I'm also not sure BLOBs would do anything for me---it'd still be "streaming" data to the client instead of letting the client handle its downloads. – Bytewave Sep 25 '16 at 03:44

1 Answers1

0

I solved this using Guzzle's LazyOpenStream class. Seems to work flawless now!

Edit: So, while this didn't initially appear to work, it turns out some file permissions were screwed up on nginx's end since I changed the user---nginx no longer owned its FastCGI cache directory. That's fortunately been fixed now, and everything seems to work.
Protip if you're in my situation: Read The Frackin' Logs!

Bytewave
  • 597
  • 1
  • 8
  • 20