Uploading PDF files as base64 strings in PHP and saving it in the hard-disk.
Tags: vue, php, base64string, pdf
Published: 2020-02-14 04:33:44

Hi there!

If you’re reading this post, chances are you’re having some issues when trying to upload (PDF) files as base64 strings to later store them “physically” in the hard-disk. No worries, it might be simpler than you think and I got you covered in this article. 😉

I’ve spent a few hours on the other day trying to figure out how to do it right. Neither Google nor Stackoverflow helped me at that time, as I searched for a while without any luck on finding any working solution! So, I hope this can help you.

First, a bit of context.

My team and I am building a Single Page Application (SPA) CRM which has a feature where the employees are required to upload a PDF file, via an ajax call against a RESTful API. As per the requirements, once received, the PDF file should be “physically” stored in the server alongside other documents (not in the database).

The approach taken was to convert the PDF file into a base64 string and submit that alongside the complementary data via POST method. The API, then, would be responsible to get that string and reconstruct the file to be stored in the disk.

Implementing this was fairly simple, however, it took us a while until we manage to properly revert the base64 string into the PDF file to be saved.

Here is how we’ve initially coded it:

```ts

// <file>.ts

// Converting a PDF file to a base64 string with Javascript. 
// This method is part of a bigger Vue.js component.

getFileInfo(evt: any): void {
  const reader: FileReader = new FileReader();
  const files: Array<any> = evt.target.files || evt.dataTransfer.files;

  reader.addEventListener(
    'load',
    () => {
      this.form.file_path = reader.result;
    },
    false
  );

  if (files[0]) {
    reader.readAsDataURL(files[0]);
  }
} // getFileInfo

```


```php

// <file>.php
// The non-working solution for converting a base64 to PDF with PHP.

public function uploadFileFromBlobString($base64string = '', $file_name = '', $folder = '')
{
    $file_path = "";
    $result = 0;
    
    // Convert blob (base64 string) back to PDF
    if (!empty($base64string)) {
        $base64data = base64_decode($base64string, true);
        $file_path  = "{$folder}/{$file_name}";

        // Return the number of bytes saved, or false on failure
        $result = file_put_contents("{$this->_assets_path}/{$file_path}", $base64data);
    }
    
    return $result;
} // uploadFileFromBlobString

```

With the above approach, everything was working fine except by the fact that the saved PDF file was getting “corrupted” and one was not been able to open it back.

The problem was that when converting the PDF file to a base64 string, it receives an extra piece of data as a prefix ( `data:application/pdf;base64,`) which when converted back to PDF simply corrupts the file.

So, as you may have already figured out, the solution was simply removing the base64 header from the string before converting it back to PDF, as follows:


```php

// <file>.php
// The working solution for converting a base64 string to a PDF file with PHP. 

public function uploadFileFromBlobString($base64string = '', $file_name = '', $folder = '')
{

    $file_path = "";
    $result = 0;

    // Convert blob (base64 string) back to PDF
    if (!empty($base64string)) {

        // Detects if there is base64 encoding header in the string.
        // If so, it needs to be removed prior to saving the content to a phisical file.
        if (strpos($base64string, ',') !== false) {
            @list($encode, $base64string) = explode(',', $base64string);
        }

        $base64data = base64_decode($base64string, true);
        $file_path  = "{$folder}/{$file_name}";

        // Return the number of bytes saved, or false on failure
        $result = file_put_contents("{$this->_assets_path}/{$file_path}", $base64data);
    }

    return $result;
} // uploadFileFromBlobString

```

As you may see above, to get it working we just had to include the following conditional block to the function we’ve written before:

```php

// Detects if there is base64 encoding header in the string.
// If so, it needs to be removed prior to saving the content to a physical file.
if (strpos($base64string, ',') !== false) {
    @list($encode, $base64string) = explode(',', $base64string);
}


```

And if the base64 prefix is found, all that needs to be done is removing it from the string before writing it back in the hard disk as a PDF file! 🤘

That’s pretty much it. 

I hope it can help you to not be struggling with such a simple issue, as I was for a few hours until figure this out! 😉

Happy coding! 🤘