Cara menyimpan file pdf ke database mysql

Views: 110

Cara menyimpan file pdf ke database mysql
0 0

Read Time:6 Minute, 55 Second

Setiap kali jika kita membuat fitur upload file umumnya menggunakan cara paling mudah, yaitu file di upload dalam bentuk utuh ke salah satu folder di server. Demikian juga jika akan melakukan download, cukup membaca dari folder server dan menampilkan dialog save file untuk user. Namun hal ini tentunya akan mengurangi portabilitas aplikasi dan jika file yang disimpan bersifat confidential, tentu akan mengurangi tingkat keamanannya.

Salah satu solusi upload file adalah dengan menyimpannya dalam database. File bisa dalam format apa saja, baik pdf, image maupun dokumen-dokumen Office. Tentunya file tidak bisa disimpan seperti saat kita menyimpannya pada folder di server. Kita harus melakukan konversi file tersebut dan menyimpannya dalam type file khusus. Artikel ini akan memberikan tips bagaimana menyimpan file dalam format Base64 pada type field Blob pada database MySQL.

Seperti diketahui bahwa MySQL memiliki type field untuk menyimpan data besar dalam bentuk Blob. Ada 4 type Blob dengan masing-masing kapasitasnya:

  • TinyBlob sampai dengan 255 bytes
  • Blob sampai dengan 64 KB
  • MediumBlob sampai dengan 16MB
  • LongBlob sampai dengan 4GB

Dengan kapasitas LongBlob yang begitu besar, bahkan format file movie juga dapat disimpan di dalamnya. Namun tentunya ukuran ini masih belum seberapa, karena kenyataannya ada banyak lagi file-file yang berukuran lebih dari 4GB.

Mari kita siapkan dahulu table untuk menampungnya. Di sini saya menyiapkan sebuah table bernama draft_naskah sebagai berikut:

CREATE TABLE `draft_naskah` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `nama_file` VARCHAR(50) NULL DEFAULT NULL,
    `file_data` LONGBLOB NULL,
    `mime` VARCHAR(50) NULL DEFAULT NULL,
    `size` VARCHAR(50) NULL DEFAULT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)

Kita menyiapkan field nama_file untuk menyimpan nama file asli, mime untuk type file dan size untuk menampung ukuran file. Informasi ini berguna nantinya saat kita akan menampilkan ataupun men-download file tersebut.

Pertama kita akan melihat bagaimana file tersebut disimpan dalam database. Saya tidak merinci bagaimana tampilan front-end blade untuk melakukan upload file, tetapi hanya bagian input file saja sebagai berikut:

<input type="file" name="nama_file" id="nama_file" style="display: none;" onchange="loadFile()">
<label for="nama_file" class="btn btn-round btn-warning" >Pilih File</label>

Perhatikan bahwa untuk style saya menggunakan Bootstrap 4, sehingga saya bisa memberikan button custom bukan bawaan dari input type file standar. Saat button di klik dan file sudah dipilih, maka fungsi JavaScript “loadFile()” akan dieksekusi. Berikut isi script fungsi tersebut:

function loadFile() {
   var filePath = document.getElementById('nama_file').value;
   var allowedExtensions = /(\.pdf|\.jpg|\.doc|\.docx|\.ppt|\.pptx|\.txt)$/i;
              
   if (!allowedExtensions.exec(filePath)) { 
      alert('Hanya jenis file PDF, JPG, MS. Word, PowerPoint dan text yang diperbolehkan!'); 
      filePath = document.getElementById('nama_file').value = '';
      return false; }  
   else {
      document.getElementById('display_file').innerHTML = document.getElementById('nama_file').files[0].name;
      return true; }
}

Batasan file yang diperbolehkan untuk di upload dalam contoh ini adalah PDF, JPG, Doc dan Docx, Ppt dan Pptx. Silakan tambahkan ekstension file yang ingin bisa di upload. Perlu diperhatikan bahwa fungsi ini hanya untuk filter dan menampilkan nama file yang akan di upload, sedangkan proses upload akan dijalankan oleh aplikasi back-end, setelah form yang berisi tag input type file di submit.

Proses back-end saat melakukan penyimpanan file tidaklah rumit. Pertama kita harus membuat Model Draftnaskah untuk mendefinisikan nama table. Isi dari Model Draftnaskah adalah:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Draftnaskah extends Model
{
    protected $table = 'draft_naskah';
    protected $primaryKey = 'id';
}

Untuk Controller, saya tidak menampilkan bagian lengkapnya, dengan asumsi anda sudah memahami resources Laravel dalam sebuah Controller. Di sini saya hanya menampilkan fungsi store() saja.

<?php

namespace App\Http\Controllers;

use App\Draftnaskah;
   .
   .
   .

public function store(Request $request) {
   $target_file = $request["nama_file"];
   $t_draft_naskah = new Draftnaskah;
   if (!is_null($target_file)) {
      $t_draft_naskah->nama_file = $target_file->getClientOriginalName(); 
      $t_draft_naskah->file_data = base64_encode(file_get_contents($target_file->getRealPath()));
      $t_draft_naskah->mime = $target_file->getMimeType();
      $t_draft_naskah->size = $target_file->getSize();
   }
   $t_draft_naskah->save();
}

Semua fungsi-fungsi terkait file seperti getClientOriginalName(), getMimeType() dan getSize() adalah bagian dari fungsi PHP. Demikian juga untuk melakukan encode isi file yang di-upload menggunakan base64_encode() tanpa perlu use library eksternal.

Setelah berhasil tersimpan, cek database anda, maka pada field file_data akan tampak karakter-karakter random yang merupakan hasil encode dari file yang disimpan. Demikian juga mime akan tersimpan sesuai type file.

Selanjutnya, saat retrieve ada 2 cara yang dapat digunakan. Pertama, untuk file PDF umumnya bisa langsung ditampilkan di browser. Siapkan sebuah button untuk menampilkan file PDF ini.

<div class="col-md-6 text-center" id="display_file">{{$draftnaskah->nama_file}}</div>
<div class="col-md-6 text-center">    
   <button type="button" id="open_file" class="btn btn-round btn-primary" onclick="openFile('{{ $draftnaskah->file_data }}')">Tampilkan</button>
</div>

Tentunya bagian front-end (blade) ini dipanggil dari salah satu fungsi dalam Controller (misalnya edit), dimana kita harus mendefinisikan variable yang menampung row table data yang akan ditampilkan. Dalam file blade contoh di atas, nama_file ditampilkan dan sebuah button disiapkan untuk menampilkan isi file tersebut. Saat diklik, fungsi JavaScript openFile() akan dieksekusi dengan mengirimkan argumen isi file_data (yang berformat Base64). Kita lihat bagaimana proses file ditampilkan pada tab baru browser.

function openFile(dataFile) {
   if (dataFile != '') {
      var w = window.open();
      var obj = document.createElement('object');
      obj.style.width = '100%';
      obj.style.height = '100%';
      obj.type = 'application/pdf';
      obj.data = 'data:application/pdf;base64,' + dataFile;
      w.document.body.appendChild(obj);
   } else {
      alert('Tidak ada lampiran file!');
   }
}

Di sini kita membuat sebuah object untuk menampung hasil encode argumen dataFile yang akan ditampilkan. Pada property obj.type sebenarnya adalah mime dari dataFile, tetapi langsung di hardcode di sini karena hanya file PDF yang bisa ditampilkan langsung oleh browser (file image juga bisa). Kemudian property obj.data, selain mime, juga isi dari dataFile yang kita ambil dari field file_data dengan tambahan informasi  format base64 yang kita tulis sesudah mime. Dengan fungsi ini, maka isi file berupa PDF akan langsung ditampilkan dalam tab baru browser (karena perintah w.document.body.appendChild()). Fungsi ini tidak bisa dijalankan untuk type file Office. Yang bisa kita lakukan adalah memberikan fitur download untuk file tersebut sesuai format aslinya. Untuk itu fungsi openFile() memerlukan 3 argumen agar bisa dieksekusi dengan baik.

Pertama, kita lihat bagaimana argumen ini dikirimkan oleh event onclick pada button sebagai berikut:

<div class="col-md-4 text-center" id="display_file">{{$draftnaskah->nama_file}}</div>
<div class="col-md-4 text-center">    
   <button type="button" id="open_file" class="btn btn-round btn-primary" onclick="openFile('{{ $draftnaskah->file_data }}', '{{ $draftnaskah->nama_file }}', '{{ $draftnaskah->mime }}')">Download File</button>
</div>

Hampir sama seperti sebelumnya, saat button diklik maka fungsi openFile() akan dieksekusi dengan mengirimkan 3 argumen. Kali ini, openFile() akan menampilkan dialog download yaitu lokasi folder untuk menyimpan file yang akan di download.

function openFile(dataFile, namaFile, mimeFile) {
   var element = document.createElement('a');
   element.setAttribute('href', 'data:'+mimeFile+';base64,'+dataFile);
   element.setAttribute('download', namaFile);

   element.style.display = 'none';
   document.body.appendChild(element);
   element.click();
   document.body.removeChild(element);
}

Berbeda dengan sebelumnya, kali ini yang dibuat adalah sebuah element HTML yakni tag “a” dan sebagai attribute ‘href’ adalah hasil decode dataFile yang merupakan isi dari field file_data (Base64 dari isi file yang kita upload sebelumnya). Perhatikan bahwa untuk mime harus kita tambahkan string ‘data:’ di awal dan ‘;base64,’ di akhir sebelum dirangkai dengan dataFile. Ini untuk menentukan bahwa data yang akan di download merupakan type sesuai dengan mime, dan harus di decode dengan Base64 agar bisa kembali ke format semula. Sesudah itu, attribute ‘download’ kita isi dengan argumen namaFile, agar saat di download sudah diberikan nama sesuai nama originalnya. Element yang terbentuk tidak perlu ditampilkan, tetapi langsung dijalankan event click() nya. Setelah eksekusi download selesai, maka element bisa dihapus.

Saya sudah mencoba kedua fitur ini, baik untuk menampilkan file PDF maupun untuk men-download file Office Word dan PowerPoint yang berisi teks dan gambar. Semua bisa ditampilkan sesuai file originalnya. Semoga bermanfaat.

Happy

0 %

Sad

0 %

Excited

0 %

Sleepy

0 %

Angry

0 %

Surprise

0 %