phpwordpresswoocommercedownload

Downloadable product served dynamically by external PHP script gives "file not found"


In my WooCommerce shop I need to sell digital files (JPEG images) that are dynamically served by a PHP script. (This is because the images come from a huge remote catalogue with 10,000s of images, which we must retrieve on demand through their API. It's not practical to keep local copies of all the JPEGs.)

I have written a PHP script that serves a JPEG image via the API, given its catalogue identifier, something like this: https://example.com/fetch_image.php?id=12345

The PHP script looks like this (simplified):

$ch = curl_init();
...
$result = curl_exec($ch); # fetch the desired JPEG image data
...
header('Content-Type: image/jpeg');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="test.jpg"');
header('Content-Description: File Transfer');
echo $result;

If I visit this script in my browser, I get the test.jpg image successfully.

So I tried setting this script's full URL as the download URL for the WooCommerce product. It was rejected:

The downloadable file fetch_image.php?id=12345 cannot be used as it does not have an allowed file type. Allowed types include: jpg|jpeg|jpe, gif, png, bmp, tiff|tif, [...etc.]

OK, fine, I don't want to "allow php as a file type" (sounds like a security headache). So let's try another approach: I set up an .htaccess redirect so that I can access my script with a jpg URL:

RewriteRule ^REDIRECT_shop_download.jpg https://example.com/fetch_image.php [L,R=301]

Now I can use this URL, which WooCommerce will accept:

https://example.com/REDIRECT_shop_download.jpg?id=12345

Again, this works fine when manually visited in the browser. However, when I use this as the WooCommerce product download URL, and I purchase the product, and click my download link, I get an error page that says File not found. This error still occurs even if I remove the header calls from my PHP script (so it serves the file without returning it as test.jpg).

I have no idea how to diagnose this. What's wrong, and how can I make it work with the valid download URL that I have provided?


Solution

  • I have found a workaround, which is to store the file-generating PHP script on a different domain and server (along with the JPG htaccess trick I described above).

    My original problem only seems to occur when the script is on the same domain, which causes it to fetch the file directly/locally instead of fetching it like a normal URL.

    To me this workaround is preferable to writing code for WordPress 'hooks' etc. which are more complicated to understand, and are liable to change and require rewriting the code over time to maintain compatibility.