When user tries to download .iso, tar.gz, or .deb from my website php is opening the file instead of downloading it. I'm having a problem with a download script. It runs fine on my local apache server, but when I put it on the my webhost's apache server, it goes crazy. Here's the script:

<?php

$php_scripts = '../../php/';
require $php_scripts . 'PDO_Connection_Select.php';
require $php_scripts . 'GetUserIpAddr.php';
function mydloader($l_filename=NULL){


    $ip = GetUserIpAddr();
       if (!$pdo = PDOConnect("foxclone_data"))
      { echo "unable to connect";
          exit;
      }

    if( isset( $l_filename ) ) {  

        header('Content-Type: octet-stream');
        header("Content-Disposition: attachment; filename={$l_filename}");
        header('Pragma: no-cache');
        header('Expires: 0');        
        readfile($l_filename);

      }

    else {
        echo "isset failed";
        }  
}
mydloader($_GET["f"]);
exit;

When I say "it goes crazy", I get errors saying that the header values have already been set by apparently by the PDOConnect. Then it actually reads the file. The files being downloaded are .iso, .deb, and .tar.gz. Here's a link to a screenshot:

[img]https://i.imgur.com/2SqiLu4.png[/img]

Dani AI

Generated

This is the classic "headers already sent" situation. 's fix (removing stray whitespace and moving the DB work after the download headers) is exactly the right direction, and correctly called out that any echoed text from the PDO connection will break header delivery. The browser will see output before your Content-Disposition header and treat the response differently.

Practical steps to find and fix the cause:

  • Use headers_sent($file, $line) to locate where output began; the PHP manual shows how to read that return info (headers_sent()).
  • Inspect every included file for leading/trailing whitespace or a UTF-8 BOM; save pure-PHP files without the closing ?> tag to avoid accidental output.
  • Disable display_errors in production (log errors instead) so warnings or notices do not send text before headers.

Hardening and best practices for a robust download endpoint:

  • Force download using the correct Content-Type (application/octet-stream) and a quoted Content-Disposition with only a sanitized basename() value. Include Content-Length when possible and use streaming (readfile() or server-side sendfile support) for large files (readfile()).
  • Never echo or print from utility functions like your DB connector; return errors or throw exceptions and log them.
  • Sanitize $_GET input (whitelist filenames or map IDs to paths) to prevent directory traversal and information leaks.
  • For very large files or high traffic, offload delivery to the webserver using X-Sendfile/X-Accel-Redirect if available.

If the problem persists on the host but not locally, check for host-configured auto_prepend_file, output buffering settings, or injected banners (use phpinfo() to inspect). The quickest diagnostic is headers_sent() plus a careful sweep for stray output and BOMs.

Recommended Answers

All 2 Replies

Fixed by removing blank spaces and moving the db connection code after the headers. Works on both my server and the web host.

Glad you got it fixed. I was going to say, the problem is that you are echo'ing out the "unable to connect" string before calling header(). You can't echo anything to the screen before any header calls.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.