Use MySQL BLOB column with PHP to store .pdf file

Like always I am sharing new things I learn here on my blog. I was recently working on a requirement for a LAMP stack web application reporting dashboard in which I needed to store – and eventually – retrieve a .pdf file. I have read in several places (this fantastic book is a great resource) that a viable option is storing images or documents (.pdf in this case) in the actual database table as opposed to on the server file system. MySQL has the BLOB datatype that can be used to store files such as .pdf, .jpg, .txt, and the like. In this blog post, I cover how I accomplished uploading and storing the actual .pdf file in a BLOB column in MySQL using PHP. Any corrections, tips, pointers, and recommendations for best practices are always welcome. We all learn as we go!!!


Self-Promotion:

If you enjoy the content written here, by all means, share this blog and your favorite post(s) with others who may benefit from or like it as well. Since coffee is my favorite drink, you can even buy me one if you would like!


I am using a table named ‘project_pdf’ with 3 columns (see accompanying screenshot) to store the data:

  • ‘id’: type INTEGER
  • ‘project_name’: type TEXT
  • ‘pdf_doc’: type BLOB

phpMyAdmin database table description
Table structure for the project_pdf table.

With the below simple HTML web form, we can collect the ‘project_name’ and enable the .pdf file attachment upload:

image of web form in the browser
Simple web form to upload a pdf to the database.

Below is the HTML source code for the above web form:

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"/>
    <title>Upload PDF</title>


    </p><h4 class="text-center" style="margin-top: 100px;">Upload A PDF To The Database</h4>
<div class="d-flex justify-content-center align-self-center" style="margin-top: 115px;">
    <form action="submit.php" method="POST" accept-charset="utf-8" enctype="multipart/form-data">
        <div class="formgroup container-fluid">
            <label for="project_name">Project Name</label>
            <input type="text" name="project_name"/>
        </div>
        <div class="formgroup container-fluid">
            <input type="file" name="pdf_file" accept=".pdf"/>
            <input type="hidden" name="MAX_FILE_SIZE" value="67108864"/> <!--64 MB's worth in bytes-->
        </div>
        <div class="formgroup container-fluid">
            <label for="submit">Submit To Database</label><br />
            <input type="submit" name="submit"/>
        </div>
    </form>
</div>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>

Looking at the code…

We will use this PHP code stored in a script submit.php – which is the form action – along with some best practices utilizing if/else conditional blocks and wrapping all of the database operations in a try/catch block to complete the .pdf INSERT in the MySQL BLOB column:

<!?php
if (isset($_POST['submit']) && !empty($_FILES['pdf_file']['name'])) {
     //a $_FILES 'error' value of zero means success. Anything else and something wrong with attached file.
    if ($_FILES['pdf_file']['error'] != 0) {
        echo 'Something wrong with the file.';
    } else { //pdf file uploaded okay.
        //project_name supplied from the form field
        $project_name = htmlspecialchars($_POST['project_name']);

        //attached pdf file information
        $file_name = $_FILES['pdf_file']['name'];
        $file_tmp = $_FILES['pdf_file']['tmp_name'];
        if ($pdf_blob = fopen($file_tmp, "rb")) {
            try {
                include __DIR__."/includes/DatabaseConnection.php";

                $insert_sql = "INSERT INTO `project_pdf` (`project_name`, `pdf_doc`)
                              VALUES(:project_name, :pdf_doc);"
;

                $stmt = $pdo->prepare($insert_sql);
                $stmt->bindParam(':project_name', $project_name);
                $stmt->bindParam(':pdf_doc', $pdf_blob, PDO::PARAM_LOB);

                if ($stmt->execute() === FALSE) {
                    echo 'Could not save information to the database';
                } else {
                    echo 'Information saved';
                }
            } catch (PDOException $e) {
                echo 'Database Error '. $e-&gt;getMessage(). ' in '. $e-&gt;getFile().
                    ': '. $e-&gt;getLine();
            }
        } else {
            //fopen() was not successful in opening the .pdf file for reading.
            echo 'Could not open the attached pdf file';
        }
    }
} else {
    //submit button was not clicked. No direct script navigation.
    header('Location: choose_file.php');
}

Verify the button is clicked and a file is attached

The first if/else block verifies that the ‘submit’ button from the form has been clicked and that the ‘pdf_file’ field has an attachment using the PHP functions isset() and empty() (the converse of truth by negating with the not ! operator for the empty() function):

1
isset($_POST['submit']) && !empty($_FILES['pdf_file']['name']))

Tip: More validation can be implemented here to verify the file type is an actual .pdf since that file type is what we are expecting to store in the database.

Informational: Visit the official PHP online documentation for more information on isset() and empty().

Check PHP $_FILES array for errors

The $_FILES array provides several related error codes for file attachments. A value of 0 (zero) means everything is okay with the file and it is successfully uploaded. In this particular if/else, block if that value is not 0 (zero), then we echo in the browser that something is wrong with the file upload:

1
$_FILES['pdf_file']['error'] != 0

Related: See the official PHP online documentation for more information on file upload errors.

PHP $_POST and $_FILES Data

The $_POST associative array has the value for the ‘project_name’ input field captured in the form and sent through the HTTP POST method. Likewise, the $_FILES associative array has several values for a file or attachment. I am assigning 2 of them to variables, but using only one – ['tmp_name'] – in the subsequent code:

  • ['name'] – The actual file name from the client. (Could be used in a file name column if needed
  • ['tmp_name'] – Temporary file name of the uploaded file as stored on the server.

1
2
3
$project_name = htmlspecialchars($_POST['project_name']);
$file_name = $_FILES['pdf_file']['name'];
$file_tmp = $_FILES['pdf_file']['tmp_name'];

Related: Read more about POST upload methods in the official online PHP documentation.

Read in .pdf binary data and prepare to store in MySQL BLOB column with PHP

The call to fopen() reads in the file in binary format ("rb") into a ‘$pdf_blob’ variable. If fopen() cannot open the file, this if/else block echo‘s the message in the else block to the browser:

1
$pdf_blob = fopen($file_tmp, "rb")


MySQL database connection and prepared statements

Finally, we look at the entire try/catch block.

I have all database connection information stored in a separate file named DatabaseConnection.php and include it in the script at this point using the include directive.

Since we are introducing user-supplied input from the web form into the database, we use prepared statements leveraging the PHP PDO methods:

  • prepare()
  • bindParam()
  • execute()

INSERT .pdf file into MySQL BLOB column with PHP

If the call to execute() is not successful, we echo a message to the browser that the information could not be saved. Otherwise, the data is successfully inserted and we echo ‘Information saved’:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
try {
    include __DIR__."/includes/DatabaseConnection.php";

    $insert_sql = "INSERT INTO `project_pdf` (`project_name`, `pdf_doc`)
                  VALUES(:project_name, :pdf_doc);"
;

    $stmt = $pdo->prepare($insert_sql);
    $stmt->bindParam(':project_name', $project_name);
    $stmt->bindParam(':pdf_doc', $pdf_blob, PDO::PARAM_LOB);

    if ($stmt->execute() === FALSE) {
        echo 'Could not save information to the database';
    } else {
        echo 'Information saved';
    }
} catch (PDOException $e) {
    echo 'Database Error '. $e->getMessage(). ' in '. $e->getFile().
        ': '. $e->getLine();   
}

Note: It is generally not a good practice to echo any sort of database error information to the browser. Errors should be written to a log file instead. However, for the purpose of this blog post as a learning experience, I echo out any exceptions that may arise in the catch block.


Using the form to store .pdf in MySQL BLOB column with PHP

Let’s try out the form and PHP code to verify the upload works. Here is a simple sample .pdf file I created for a demo run:

image content of pdf document
Contents of SamplePDF.pdf document to upload with form.

See this screenshot in which I fill in the ‘project name’ field with a generic ‘First Project’ name and attach the SimplePDF.pdf file:

image of web form for submit
Filled out web form with pdf attachment for upload.

Upon clicking the ‘Submit’ button, the information is successfully stored in the database and the success message is displayed in the browser:

image of browser message
Message displayed in the browser after successful pdf upload.

Here is the data saved in the MySQL database table from the successful upload via our web form and the PHP code:

phpMyAdmin image of record in database table
The project_pdf table with inserted pdf and project name.

It works!!!

In the next blog post, I will cover how to retrieve the .pdf file from the database and display it in the browser. If you see anything in the code that I can improve on or any mistake, please let me know via the comments section below.

Additional PHP/MySQL Reading

Be sure and visit these other blog posts I have written on PHP and MySQL:

Like what you have read? See anything incorrect? Please comment below and thanks for reading!!!

A Call To Action!

Thank you for taking the time to read this post. I truly hope you discovered something interesting and enlightening. Please share your findings here, with someone else you know who would get the same value out of it as well.

Visit the Portfolio-Projects page to see blog post/technical writing I have completed for clients.


To receive email notifications (Never Spam) from this blog (“Digital Owl’s Prose”) for the latest blog posts as they are published, please subscribe (of your own volition) by clicking the ‘Click To Subscribe!’ button in the sidebar on the homepage! (Feel free at any time to review the Digital Owl’s Prose Privacy Policy Page for any questions you may have about: email updates, opt-in, opt-out, contact forms, etc…)

Be sure and visit the “Best Of” page for a collection of my best blog posts.


Josh Otwell has a passion to study and grow as a SQL Developer and blogger. Other favorite activities find him with his nose buried in a good book, article, or the Linux command line. Among those, he shares a love of tabletop RPG games, reading fantasy novels, and spending time with his wife and two daughters.

Disclaimer: The examples presented in this post are hypothetical ideas of how to achieve similar types of results. They are not the utmost best solution(s). The majority, if not all, of the examples provided, is performed on a personal development/learning workstation-environment and should not be considered production quality or ready. Your particular goals and needs may vary. Use those practices that best benefit your needs and goals. Opinions are my own.

3 thoughts on “Use MySQL BLOB column with PHP to store .pdf file

Hey thanks for commenting! Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.