1

I'm having trouble getting my successfully uploaded files that are sitting in a blob field in a table called appFiles in my MySQL database, to come back out and display. I've read a lot of demos, most are similar but none have solved my issue. I've done this once before a long time ago but the code for that old project was done using mysqli and I want to become 100% PDO based. Here is my section of code that deals with the file:

} else if($ctoken === $utoken) {
    // Our tokens match, proceed with the view

    $stmt = $conn->prepare("SELECT fileMime, fileSize, fileName, file FROM $database.appFiles WHERE fileID = :fileid");
    $stmt->bindParam(':fileid', $_GET['fid'], PDO::PARAM_INT, 11);
    $stmt->execute();
    $fRes = $stmt->fetchAll();

    header('Content-Disposition: attachment; filename="' . $fRes[0][fileName] . '"');
    ob_clean();
    flush();
    echo $fRes[0][file];
    exit;
}

Now I know the data is being selected out of the database successfully. I can check this easily by performing a var_dump($fRes). It does appear to be all there, though of course the majority of it is a binary mess and seems to come up as mostly question marks among a lot of other mess that makes no sense on screen.

When I test it on a PDF document it simply spits out binary on the screen. When I test it with a DOC/DOCX file it does at least try to open it in MS Word but then tells me that the file conversion broke and displays an empty document (when showing the docx) or displays an incorrectly long document with gobblygook mess for hundreds of pages (when trying to display the doc file).

I've tried this with a range of different header options, most with different results, none with the desired one. So how do I get it to SUCCESSFULLY spit out the file in an intelligible format?

EDIT Thanks to the link supplied below by Darren, I'm now using this as my code for viewing the files stored within the database:

try {
    $stmt = $conn->prepare("SELECT * FROM $database.users WHERE uID = :uid");
    $stmt->bindParam(':uid', $uID, PDO::PARAM_INT, 11);
    $stmt->execute();
    $uRes = $stmt->fetchAll();
} catch(PDOException $e) { catchMySQLerror($e->getMessage()); }

$ctoken = $_COOKIE['cookieToken'];
$utoken = $uRes[0]['sessionToken'];

if($ctoken !== $utoken) {
    // Our tokens don't match, kill the session
    header("Location: ./logOut.php");
    exit;
} else if($ctoken === $utoken) {
    // Our tokens match, proceed with the view

    $stmt = $conn->prepare("SELECT fileMime, fileSize, fileName, file FROM $database.appFiles WHERE fileID = :fileid");
    $stmt->bindParam(':fileid', $_GET['fid'], PDO::PARAM_INT, 11);
    $stmt->execute();
    $fRes = $stmt->fetchAll();

    header("Content-Type: application/octet-stream");
    header("Content-Transfer-Encoding: Binary");
    header("Content-disposition: attachment; filename=\"".$fRes[0][fileName]."\"");
    echo readfile($fRes[0][file]);

    exit;
}

They now at least appear to prompt me to either download and save them, or open them with the correct viewer. This is nice. However something is still very wrong as each time the file arrives as only 0 bytes... Anyone got a notion how to fix this problem and make it work ok, finally?

SECOND EDIT I've done a LOT of testing on this situation and discovered that retrieving the file from the database is in fact no the problem at all. It appears as though there is a problem with my uploading system and the files are getting traumatised somehow there. If I replace the file that was uploaded (the name, type, size etc are all imported correctly) with the original file by using phpmyadmin to "reload" it up into the database, it is then handled perfectly as desired by the download interface. Lesson to learn here - don't think just because the file looks right by all it's attributes like size, mime, name etc, that it IS correctly uploaded! Now to discover why/where my upload is messing up the file.... if you might have an idea where or why this is happening, please visit here

Community
  • 1
  • 1
Cassandra
  • 284
  • 4
  • 18
  • You may want to read [this](http://stackoverflow.com/a/7263943/2518525) which outlines how you can force the download. – Darren Apr 07 '15 at 04:54
  • What does `file` column contain? If it's the file contents then you just have to echo it. If it's a path to the file then you just have to call `readfile` (without echo). – hynner Apr 08 '15 at 17:34
  • Hello hynner. The file itself is stored within the MySQL database as a medium blob, and it is not stored anywhere in a directory. So it is part of the data that is being extracted from the MySQL PDO request, and $fRes[0][file] is the (supposed to be) the file itself. – Cassandra Apr 08 '15 at 17:41
  • I've changed the last line from - echo readfile($fRes[0][file]); - to become - echo $fRes[0][file]; but the result is the same. It's 1 byte in size, which is 1 byte more than before but certainly unusable and much less than it should be....! – Cassandra Apr 08 '15 at 17:44

1 Answers1

0

Just replace

echo readfile($fRes[0][file]); 

By

echo $fRes[0][file]; 

According to your code the field file contains the file content. Therefore you simply echo it.

Lorenz Meyer
  • 19,166
  • 22
  • 75
  • 121
  • Hi Lorenz, please check my last recent comment above - I've done exactly what you nominated but it is not working. – Cassandra Apr 08 '15 at 18:03
  • So tell me : where is the file content in the database? – Lorenz Meyer Apr 08 '15 at 18:09
  • The file content is stored in a separate table specifically for file collection and handling, within a field that is set up as medum blob (files are limited to 5Mb in size, max). This field has the attribute of BINARY. No other special attributes are set up on it. – Cassandra Apr 08 '15 at 18:18
  • Answer by Lorenzo accepted as it is correct, just answered the question I was not really needing, since discovering the actual problem is with the upload process and not the extraction/download process at all. – Cassandra Apr 08 '15 at 19:29