[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

php fopen failing every other time

Posted on 2014-07-10
5
Medium Priority
?
663 Views
Last Modified: 2014-07-11
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.
0
Comment
Question by:loki0609
  • 2
  • 2
5 Comments
 
LVL 84

Expert Comment

by:Dave Baldwin
ID: 40189046
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
 
LVL 2

Author Comment

by:loki0609
ID: 40189058
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
 
LVL 84

Assisted Solution

by:Dave Baldwin
Dave Baldwin earned 1000 total points
ID: 40189269
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
 
LVL 111

Accepted Solution

by:
Ray Paseur earned 1000 total points
ID: 40190224
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
 
LVL 2

Author Comment

by:loki0609
ID: 40190999
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

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
3 proven steps to speed up Magento powered sites. The article focus is on optimizing time to first byte (TTFB), full page caching and configuring server for optimal performance.
In this tutorial viewers will learn how to embed an audio file in a webpage using HTML5. Ensure your DOCTYPE declaration is set to HTML5: : The declaration should display (CODE) HTML5 is supported by the most recent versions of all major browsers…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Suggested Courses
Course of the Month17 days, 18 hours left to enroll

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question