Accessing GridFS file stored / PHP

For a project, I’m want to be able to download a PDF file that was previously saved in a MongoDB document using GridFS.

I’m a new developer and this is my first time using the Upload/Download and streams notions so I might be going to it completely wrong and missing something obvious but I can’t see where it is that I might be going at it wrong.
For all I know maybe my Upload is bad to start and that’s why I can’t donwload anything !

I have been looking at this MongoDB doc to try and get the Download working, but to no effect.

I have a page displaying all my MongoDB data in a Table (each row = one document) and in those rows a link to open a new page to Download/Consult the PDF file previously uploaded to that specific document.

The problem is that when I access that link, well nothing happens I have a blank page.

Here is the page where I display data and have a form to upload new data with a file upload if needed.

<?php
require 'vendor/autoload.php';

try {
    $mng = new MongoDB\Driver\Manager("mongodb://localhost:27017/dbname");
    $bucket = new MongoDB\GridFS\Bucket($mng, 'dbname');
    $query = new MongoDB\Driver\Query([]);
    $r = $mng->executeQuery("dbname.dbname", $query);

    if (!empty($_POST["date"])){
        $document = array(
            "num_id"         => $_POST["num_id"],
            "name"            => $_POST["name"],
            "date"    => $_POST["date"],
            "detail"           => $_POST["detail"],
        );
        if ($_FILES['pdf']) {
            $stream = $bucket->openUploadStream($_FILES['pdf']['tmp_name']);
            $document['pdf'] = $bucket->uploadFromStream($_FILES['pdf']['name'], $stream);
        }
        $single_insert = new MongoDB\Driver\BulkWrite();
        $single_insert->insert($document);
        $mng->executeBulkWrite("rs.rs", $single_insert);
    } 
} 
catch (Exception $e) {
    echo 'Exception reçue : ',$e->getMessage(),"\n";
}
?>

<table>
    <thead>
        //Columns titles for data
    </thead>
    <tbody>
        <?php foreach ($r as $document):
        $bson = MongoDB\BSON\fromPHP($document);
        $json = json_decode(MongoDB\BSON\toJSON($bson));
        ?>
            <tr>
                <td><?php echo date('d-m-Y',strtotime($json->{'date'})) ?></td>
                <td><?php echo $json->{'num_id'} ?></td>
                <td><?php echo $json->{'name'} ?></td>
                <td><?php echo $json->{'detail'} ?></td>
                <td><?php if (!empty($json->{'pdf'})) {
                    echo '<a href="file.php?id=' . $document->pdf . '">File</a>';
                    }
                    else {
                        echo "";
                    } ?></td>
            </tr>
        <?php endforeach; ?>
    </tbody>
</table>
<form action="" enctype="multipart/form-data" method="POST">
    //Other inserts for the main document(date, name, detail,..)
    <p>
        <label for="pdf">Document</label><br>
        <input type="file" id="pdf" name="pdf">
    </p>
    <p>
        <input type="submit" id="addform" value="Add">
    </p>
</form>

And here is my file.php where the User is sent after clicking a link in the Table and where I try to access the data stored by GridFS

<?php
require 'vendor/autoload.php';

try {
    $mng = new MongoDB\Driver\Manager("mongodb://localhost:27017/dbname");
    $bucket = (new MongoDB\Client)->dbname->selectGridFSBucket();
    $fileId = new MongoDB\BSON\ObjectID($_GET['id']);
    $stream = $bucket->openDownloadStream($fileId);
    $contents = stream_get_contents($stream);
} 
catch (Exception $e) {
    echo 'Exception reçue : ',$e->getMessage(),"\n";
}
?>

And with this code. Even though the $GET[‘id’] is indeed the _id of a document in dbname.fs.files I get nothing in return, not even an error.
Here is how the structure of the documents looks like using MongoDB Compass.

I hope I was clear enough and thank you for reading me thus far.

Hello Axel, did you later solve this issue, I’m currently facing the exact same issue and I’m struggling to figure it out

Based on the screenshot you shared, the fs.files document exists but contains no data. We can confirm this via the length field, which is zero, and the MD5 checksum corresponding to that of an empty string:

$ echo -n "" | md5sum
d41d8cd98f00b204e9800998ecf8427e  -

In the second script you shared, you only assign the GridFS stream’s contents to a $context variable, which is not printed. But assuming that was just an example and you’re actually printing the string, the output would still be empty since the GridFS file itself is empty.

On a related note, remember that you’ll likely need to emit a Content-Type header for the image before outputting its binary data in a web response.

If the GridFS file is empty, the root cause is likely how you’re attempting to upload it in the first place. The openUploadStream and uploadFromStream methods used here are mutually exclusive.

openUploadStream() returns a stream that you then write (e.g. fwrite()). Upon closing the stream, all of its chunk data will have been written to GridFS and its metadata document (with the length, checksum, etc.) will be created.

uploadFromStream() operates inversely. You provide it a stream (e.g. calling fopen() on the temp file). The PHP library then reads that stream in its entirety and writes the contents to GridFS (chunk(s) and metadata).

Uploading Files with Writable Streams in the PHP library’s GridFS tutorial includes code examples for both of these APIs.