php fopen failing every other time

I have a php script that goes to another url to grab a file and give the option to the user to save it. Basically we want the file to appear to download from the site they are on (nothing shady we own both sites:))

I'm using php and fopen to do this but it's failing every other or 3rd time you click the download button. It gives the stream can't be open 500 internal error.

Here is the code:

$handle = @fopen($download_url, "r");
	if (!$handle)
		die("Error opening file");

	header('Content-Description: File Transfer');
	header('Content-Type: application/octet-stream');
	header('Content-Disposition: attachment; filename="'.$download->exe_name.'"');
	header('Expires: 0');
	header('Cache-Control: must-revalidate');
	header('Pragma: public');

	
	while (!feof($handle))
		echo fread($handle, 1);
	
	fclose($handle);

Open in new window


It's really weird since it works part of the time downloading the same file.
LVL 2
loki0609Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dave BaldwinFixer of ProblemsCommented:
There could be all kinds of problems with doing that.  Network could be too busy or the file could be open and locked on the remote server.  Put a copy on the main site and see if you still have problems.
0
loki0609Author Commented:
If i put the direct url in to my browser I can get it every time.

Does locking have any effect on this since I'm opening a read only? (The file is never modified)
Is there any network switches to handle time outs?

What's the best way to accomplish this? Curl, fopen, cname mask? The end result should show that the user is downloading the file from xyz.com even though it's on yyy.com
0
Dave BaldwinFixer of ProblemsCommented:
The 'best' way is to copy the file to both servers each time it is uploaded so it is being downloaded from the server the user is on every time.  You might try 'file_get_contents' which is always read-only and doesn't pretend to be a 'file' operation like 'fopen' does.
http://us3.php.net/manual/en/function.file-get-contents.php
0
Ray PaseurCommented:
I think Dave's strategy of uploading the file to the same server that provides the download is the right strategy.  If you use cURL you can get some error information that will not be available in file_get_contents() or fopen().  This example shows how to use cURL to read from a URL and visualize error messages.  By far the most common cURL error condition is "timeout."  With file_get_contents(), a timeout condition usually results in a script failure, since the time spent waiting for file_get_contents() to complete is added to the script execution time.

<?php // /demo/curl_get_example.php
error_reporting(E_ALL);


// DEMONSTRATE THE BASICS OF CURL
// SOMETHING LIKE demo/curl_get_example.php?url=http://twitter.com


// YOU COULD HAVE SOMETHING LIKE THIS
$url = isset($_GET["url"]) ? $_GET["url"] : 'http://twitter.com';

// BUT SINCE IT IS ON MY SERVER, I HAVE HARD-CODED THIS
$url = 'https://twitter.com/RayPaseur';

// TRY THE REMOTE WEB SERVICE
$htm = my_curl($url);

// SHOW THE WORK PRODUCT OR BARK OUT ERROR MESSAGES
echo "<pre>";
echo PHP_EOL . '<strong>' . $url . '</strong>' . PHP_EOL;
echo PHP_EOL . htmlentities($htm);
echo PHP_EOL;


// A FUNCTION TO RUN A CURL-GET CLIENT CALL TO A FOREIGN SERVER
function my_curl
( $url
, $timeout=5
, $error_report=TRUE
)
{
    $curl = curl_init();

    // HEADERS AND OPTIONS APPEAR TO BE A FIREFOX BROWSER REFERRED BY GOOGLE
    $header[] = "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
    $header[] = "Cache-Control: max-age=0";
    $header[] = "Connection: keep-alive";
    $header[] = "Keep-Alive: 300";
    $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
    $header[] = "Accept-Language: en-us,en;q=0.5";
    $header[] = "Pragma: "; // BROWSERS USUALLY LEAVE THIS BLANK

    // SET THE CURL OPTIONS - SEE http://php.net/manual/en/function.curl-setopt.php
    curl_setopt( $curl, CURLOPT_URL,            $url  );
    curl_setopt( $curl, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0'  );
    curl_setopt( $curl, CURLOPT_HTTPHEADER,     $header  );
    curl_setopt( $curl, CURLOPT_REFERER,        'http://www.google.com'  );
    curl_setopt( $curl, CURLOPT_ENCODING,       'gzip,deflate'  );
    curl_setopt( $curl, CURLOPT_AUTOREFERER,    TRUE  );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, TRUE  );
    curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, TRUE  );
    curl_setopt( $curl, CURLOPT_TIMEOUT,        $timeout  );
    curl_setopt( $curl, CURLOPT_VERBOSE,        TRUE   );
    curl_setopt( $curl, CURLOPT_FAILONERROR,    TRUE   );


    // IF USING SSL, THESE MAY BE IMPORTANT
    curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, FALSE  );
    curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, FALSE  );
    curl_setopt( $curl, CURLOPT_SSLVERSION,     3      );

    // RUN THE CURL REQUEST AND GET THE RESULTS
    $htm = curl_exec($curl);

    // ON FAILURE
    if ($htm === FALSE)
    {
        // VISUALIZE ERROR MESSAGES
        if ($error_report)
        {
            $err = curl_errno($curl);
            $inf = curl_getinfo($curl);
            echo "CURL FAIL: $url TIMEOUT=$timeout, CURL_ERRNO=$err";
            var_dump($inf);
        }
        curl_close($curl);
        return FALSE;
    }

    // ON SUCCESS RETURN XML / HTML STRING
    curl_close($curl);
    return $htm;
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
loki0609Author Commented:
Thanks for the comments and info.

What i ended up doing is creating a CNAME record that went to the base of the other site and then just used header location to forward them to the file. Then when they download it, it shows downloads.xyz.com which accomplished my goal.

I couldn't copy the file over as it's a dynamic service related file. I'm fairly certain the issue is time out but it sure happens quickly.

Thanks for the info Ray, I'm planning on looking at this again later and that will definitely help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.