I have a simple image processing server that handles authentication of images, resizing, cropping, etc. If it recently did a relatively large operation such as resize an image, it will upload the new resized version back to Cloud Storage, which it will use next time that exact size is needed again.
My question is, next time someone requests that image, or the server is serving an unaltered image "directly" from the Google Cloud Storage bucket, what's the best method for my PHP server to "pass on" the data of the image to the user, using as little processing and memory as possible?
Right now my current working code boils down to:
if ($image->exists()) {
header("Content-Type: image/jpeg");
echo $image->downloadAsString();
}
Which, just from looking at it, seems like a bad way to do things. But I don't know so I'm asking.
Edit: I am not looking for the most efficient way to serve images to the client in general or in any larger scheme, I am looking for the most efficient function(s) I can use already in PHP to accomplish what I'm trying to do with as little latency, CPU usage, and memory as possible.
"What I'm trying to do" being: In a running PHP script, verify that the user can access the image, check if the resized image exists, and if it does, relay it to the client. If it doesn't, resize the image, send it back to cloud storage for later retrieval, then send the resized image to the user. The only part I'm concerned about right now is how to pass the data from the bucket to the user.
Assume all servers including the bucket itself are in the same zone. I am not using a framework. I need to serve through the webserver, and for those that I don't need to, I use a load balancer to serve directly from the cloud storage. I am not using a CDN.
CodePudding user response:
Using downloadAsStream()
and stream_copy_to_stream()
should give you the best results. Eg:
if ($image->exists()) {
header("Content-Type: image/jpeg");
stream_copy_to_stream($image->downloadAsStream(), STDOUT);
}
In this case PHP should copy file data directly to output as it is retrieved with maximal efficiency, memory or otheriwse.
If you scroll up a bit in the source downloadAsString()
just calls the stream and returns the whole thing as a string, which will cram all that file data into memory.
Also, for best results, grab the StorageObject metadata and set a Content-Length:
header. This generally makes HTTP clients behave a bit better. I believe this will be in what's returned by $image->info()
.