3

This is one I just can't figure out: I have successfully built an upload feature on a web page to upload files to a MySQL Database. When I go on the server and open them via phpMyAdmin, they all look fine... txt, jpg, pdf, etc.

Yet, after putting together THIS thing (below) to download it, I get a strange problem: All of the text documents (and all other types of files, after I change the extension to 'txt') contain HTML code of the page itself, followed by the original content!

Also, different browsers display differently after the POST. When trying to download a txt file, IE will show the correct data in the ECHO on the page itself (no downloading) with an error message just before it:

Warning: Header may not contain more than a single header, new line detected. in C:\wamp\www\ace\dmain.php on line 82.

Line 82 is 'header("Content-length...'

Neither Firefox nor Chrome show anything. They just allow me to download it.

Here's the code:

<?php
if (isset($_POST['downloadid'])) {
    $fileid = $_POST['downloadid'];
    try {
      $sql = "SELECT * FROM `datastore` WHERE `id` = '".$fileid."'";
        $results = $pdo->query($sql);echo $sql;
        while ($row = $results->fetch()) {
            $filename = $row['filename'];
            $mimetype = $row['mimetype'];
            $filedata = $row['filedata'];
            header("Content-length: strlen($filedata)");
            header("Content-type: $mimetype");
            header("Content-disposition: download; filename=$filename"); //disposition of download forces a download
            echo $filedata; 
            // die();
        } //of While
    } //try
    catch (PDOException $e) {
        $error = '<br>Database ERROR fetching requested file.';
        echo $error;
        die();    
    } //catch
} //isset
?>
Community
  • 1
  • 1
Chris Wilson
  • 203
  • 1
  • 6
  • 14
  • 3
    Yikes. You're using PDO and _still_ not binding parameters and you're making yourself vulnerable to SQL injection. **Please** (for your own good) look into `bindValue` and `prepare` on PDO. You're also `echo`ing the SQL before you change headers. This will cause the headers to not be sent unless output buffering is enabled. – Colin M Feb 21 '13 at 18:34
  • Yeah... I'm a bad boy. This is really for internal use only for a small set of employees, but I get the point. Will rewrite that. – Chris Wilson Feb 21 '13 at 18:41
  • Even for internal use it's important. Not much to stop an employee on the way out from causing some damage when they leave if this is how the code is written! I'm just trying to help you out. But you know better than me in your internal organization. – Colin M Feb 21 '13 at 18:43
  • When it's just output, should I still bind parameters and use prepare? – Chris Wilson Feb 21 '13 at 19:30
  • Yes, you should _always_ escape. Believe me, you'll be doing a favor to yourself and your company if, when you ask, "should I escape X?" you always just answer YES. – Colin M Feb 21 '13 at 19:31

3 Answers3

6

This:

header("Content-length: strlen($filedata)");

Is not going to produce what you expect. If you look at the headers in wireshark, or another method to view the request you will see that it does not contain an integer.

Use this instead:

header("Content-length: ".strlen($filedata));
datasage
  • 19,153
  • 2
  • 48
  • 54
  • Thanks for that one! I don't get the IE message anymore, but all files still have the HTML code appended to the beginning. Gak. – Chris Wilson Feb 21 '13 at 18:45
  • Your code is currently echoing the SQL statement, do you have any other output before you echo the file data? – datasage Feb 21 '13 at 18:47
  • I removed the echo $sql after I posted this. No luck. There is other output before the – Chris Wilson Feb 21 '13 at 18:54
  • Nope. Just starts out with my header file, and contiguously goes through to the end of the page. All of the page HTML is included in the file. I've read that spaces and output before can do things to disrupt this. Should I call a separate, isolated PHP page via the form? – Chris Wilson Feb 21 '13 at 19:03
  • I think you do need to isolate this. You need to make sure its called in a context where no other html is generated. – datasage Feb 21 '13 at 19:05
  • Thanks. Just did that, and it's fixed. I don't really get it. All other code seemed fine. Just a quirk with header? – Chris Wilson Feb 21 '13 at 19:14
0

After agonizing over fixing it in-place (that is, on the same page with the rest of the html and code), I decided to move it to a dedicated PHP page. After that, it worked fine.

Thanks for the comments!

Chris Wilson
  • 203
  • 1
  • 6
  • 14
-1

here is good example and complete source

Android
  • 8,995
  • 9
  • 67
  • 108