1

I'm randomly getting download errors from a link on a page. I also simplified the link to a directory for easy usage in emails for users.

On the main page the link looks like this:

a href="http://myPage.com/Mac" target="_blank" id="macDownloadButton" class="downloadbutton w-button">Download Mac version</a>

On my server, that's a directory with an index.php in it which looks like this:

<?php

// mac version
$file="http://www.myPage.com/downloads/myApp_Mac.zip";
$filename="myApp_Mac.zip";

header('Content-Transfer-Encoding: binary');  
header('Accept-Ranges: bytes');  
header('Content-Length: ' . filesize($file));  
header('Content-Encoding: none');
header('Content-Type: application/zip');  
header('Content-Disposition: attachment; filename=' . $filename);  
readfile($file); 
exit;
?>

Again, the reason I do this is so it's a simple link to send to users in email like, "http://myPage.com/Mac" and "http://myPage.com/Windows".

The weird thing is that it mostly works...but sometimes it doesn't.

What am I doing wrong?

3
  • Instead of using a URL for the readfile(), why not use a local file path? Using a URL just creates an unnecessary HTTP request to your server. Commented Jan 1, 2018 at 17:18
  • I'm not sure why I did it like that. I probably copied this from somewhere because I wasn't clear on the correct approach. I also notice that when it downloads, Safari doesn't show the total size in the progress bar, just an endless progress bar until it finishes. Commented Jan 1, 2018 at 17:22
  • Try it with a local file path instead and see if that solves your issue. Commented Jan 1, 2018 at 17:24

2 Answers 2

2

It's hard to know precisely what's wrong unless you check for errors on your readfile() call.

But you're invoking your web server from your web server here when you specify a filename starting with http. You're doing

 readfile('http://www.myPage.com/downloads/myApp_Mac.zip');

where you could just as easily do

 readfile('../downloads/myApp_Mac.zip');

and read the zip file from the local file system to send to your user.

What's more, filesize('../downloads/myApp_Mac.zip'); will yield a numerical value quickly and send it in the Content-Length header. That will allow the browser, by knowing the total size of the file you're sending, to display a meaningful progress bar.

You should remove the Accept-Ranges header; the php program you showed us doesn't honor range requests. If you lie to the browser by telling it you do honor those requests, the browser may get confused and corrupt the downloaded copy of your file. That will baffle your user.

Your Content-Disposition header is perfect. It defines the filename to be used on your user's machine in the downloads folder.

Simple operations are more reliable, and this may help you.

The reason you got stat failed with link as an error message is this: stat(2) is a operating-system call that operates on files in local and mounted file systems.

Sign up to request clarification or add additional context in comments.

1 Comment

This is great. What about the header('Content-Disposition: attachment; filename=' . $filename) line? Should that be a local link as well?
0

As previously mentioned by O. Jones you should definitely always use your local file path.

Most of my previous issues have been mostly browser related where I needed to tweak/add a http header, and in one case I needed to send all the HTTP headers in lowercase but I haven't had an issue like that in years. My personal recommendation would be to use a solid download library/function - it will make a noticeable difference to your productivity as well as rule out most browser related issues you may come across.

I have used the codeIgniter download helper for the last 3 years and recommend it for 99% of use cases. At the very least I would recommend your read through it's code - you will probably find a few cases you have never even considered such as clearing the output buffer,mime detection and even a special case for Android 2.1 as well as a few headers you may or may not need.

If all else fails I have no idea what server your running this on but if you continue to have issues I would recommend monitoring which processes your machine is running while paying close attention to ram and IO usage. I've have encountered bad/misbehaving services that run periodically using 99% of my IO or ram for short intervals at a time that caused a few really odd and unexpected errors.

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.