Tutorial Codeigniter #11: Membuat Fitur Upload File
Pada tutorial sebelumnya:
Kita sudah berhasil membuat fitur edit profile.
Namun, masih belum komplit.
User hanya baru bisa mengedit data dan password saja.
Nah, pada tutorial ini..
Kita akan mengerjakan fitur upload avatar. Sehingga user bisa mengganti avatarnya.
Kita akan memanfaatkan library upload bawaan Codeigniter untuk upload.
Sebenarnya bisa juga menggunakan Upload bawaan PHP, namun karena sudah disediakan library-nya di CI.. mengapa tidak kita manfaatkan.
Oke..
Kalau gitu, mari kita mulai!
Apa itu Library Upload?
Library upload merupakan library yang berisi class untuk upload file.
Library ini dapat kita gunakan dengan melakukan load seperti ini:
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = 100;
$config['max_width'] = 1024;
$config['max_height'] = 768;
$this->load->library('upload', $config);
Saat load library upload, kita membutuhkan variabel $config
yang berisi
konfigurasi upload.
Pada contoh di atas, kita menentukan konfigurasi seperti:
upload_path
adalah folder tujuan untuk upload file;allowed_types
adalah tipe file yang diizinkan untuk di-upload;max_size
adalah batas ukuran file yang dibolehkan;max_width
adalah batas lebar untuk file gambar;max_height
adalah batas tinggi untuk file gambar;
Selain konfigurasi ini, masih ada lagi konfigurasi yang lain. Semuanya bisa dilihat di dokumentasi.
Setelah melakukan load library, barulah kita bisa melakukan proses upload dengan memanggil method:
$this->upload->do_upload('userfile');
Perhatikan userfile
adalah nama file dari form upload.
Pastikan namanya sama seperti name
pada form input file.
<input type="file" name="userfile" size="20" />
Method do_upload()
akan menghasilkan nilai TRUE
jika upload-nya berhasil
dan FALSE
jika upload-nya gagal.
Jika upload berhasil, maka kita bisa mengambil data file yang sudah terupload dengan method:
$this->upload->data();
..dan jika gagal, kita juga bisa mengambil pesan error dari method:
$this->upload->display_errors();
Nah, biar lebih jelas..
Mari kita coba dalam project beritacoding
.
🧑💻 Latihan: Membuat Fitur Upload File
Silakan buka kembali project beritacoding
yang sudah dibuat.
Lalu kerjakan ini:
1. Controller untuk Upload Avatar
Ubahlah method upload_avatar()
pada controller admin/Setting.php
menjadi seperti ini:
public function upload_avatar()
{
$this->load->model('profile_model');
$data['current_user'] = $this->auth_model->current_user();
if ($this->input->method() === 'post') {
// the user id contain dot, so we must remove it
$file_name = str_replace('.','',$data['current_user']->id);
$config['upload_path'] = FCPATH.'/upload/avatar/';
$config['allowed_types'] = 'gif|jpg|jpeg|png';
$config['file_name'] = $file_name;
$config['overwrite'] = true;
$config['max_size'] = 1024; // 1MB
$config['max_width'] = 1080;
$config['max_height'] = 1080;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('avatar')) {
$data['error'] = $this->upload->display_errors();
} else {
$uploaded_data = $this->upload->data();
$new_data = [
'id' => $data['current_user']->id,
'avatar' => $uploaded_data['file_name'],
];
if ($this->profile_model->update($new_data)) {
$this->session->set_flashdata('message', 'Avatar updated!');
redirect(site_url('admin/setting'));
}
}
}
$this->load->view('admin/setting_upload_avatar.php', $data);
}
Penjelasan:
Pada method upload_avatar()
, kita melakukan load profile_model
yang nanti akan kita gunakan untuk menyimpan atau mengubah data avatar.
Kemudian, kita akan melakukan upload saat method ini menerima input post
.
Di sini kita menentukan konfigurasi upload sebagai berikut:
$file_name = str_replace('.','',$data['current_user']->id);
$config['upload_path'] = FCPATH.'/upload/avatar/';
$config['allowed_types'] = 'gif|jpg|jpeg|png';
$config['file_name'] = $file_name;
$config['overwrite'] = true; // tindih file dengan file baru
$config['max_size'] = 1024; // batas ukuran file: 1MB
$config['max_width'] = 1080; // batas lebar gambar dalam piksel
$config['max_height'] = 1080; // batas tinggi gambar dalam piksel
Perhatikan variabel $file_name
variabel ini berisi id dari user yang sedang login.
Id ini akan kita pakai sebagai nama file avatar.
Oh iya, karena id mengandung titik.. maka kita perlu menghapusnya dengan fungsi
str_replace()
.
Kalau tidak dihapus, memangnya kenapa?
Kalau tidak dihapus, upload filenya akan gagal.
Mungkin ini bug di Library Upload atau memang untuk nama file yang mengandung simbol tidak diizinkan.
Karena itulah kita harus membersihkan nama file dari simbol seperti titik.
Oke, berikutnya kita menentukan folder tujuan upload.
$config['upload_path'] = FCPATH.'/upload/avatar/';
Konstanta FCPATH
adalah konstanta yang berisi alamat path untuk folder project.
Jika kita menyimpan project di dalam C:\xampp\htdocs\beritacoding
,
maka FCPATH
akan berisi alamat tersebut.
Dengan demikian, kita bisa tambahkan folder /upload/avatar/
sebagai tempat menyimpan avatar yang terupload.
Lalu coba perhatikan juga konfigurasi ini:
$config['overwrite'] = true;
Ini aritnya kita akan menindih file yang sudah di-upload dengan file baru.
Jika file avatar sudah ada, maka akan ditindih dengan yang baru.
Kemudian kita lakukan upload dengan memanggil method do_upload()
.
// lakukan upload
if (!$this->upload->do_upload('avatar')) {
// saat gagal, tampilkan pesan error
$data['error'] = $this->upload->display_errors();
} else {
// saat berhasil ambil datanya
$uploaded_data = $this->upload->data();
// buat data baru untuk update avatar
$new_data = [
'id' => $data['current_user']->id,
'avatar' => $uploaded_data['file_name'],
];
// simpan data baru ke database dan redirect
if ($this->profile_model->update($new_data)) {
$this->session->set_flashdata('message', 'Avatar updated!');
redirect(site_url('admin/setting'));
}
}
Jika kita perhatikan, method upload_avatar()
menggunakan view setting_upload_avatar.php
.
View ini berisi form upload untuk upload avatar dan ini belum kita buat.
Nanti kita akan buat setelah membuat folder upload.
2. Membuat Folder Upload
Buatlah folder baru di dalam folder project dengan nama upload
.
Kemudian di dalam folder upload, buat lagi folder baru dengan nama avatar
.
Jika kamu menggunakan Linux, jangan lupa atur hak akses folder-nya agar bisa upload file.
Ketik perintah berikut:
sudo chmod 777 -R /var/www/html/beritacoding/upload/avatar/
Setelah itu, silakan lanjutkan membuat view.
3. Membuat View Form Upload
Buatlah view baru di dalam folder views/admin
dengan
nama setting_upload_avatar.php
dan isi sebagai berikut:
<!DOCTYPE html>
<html lang="en">
<head>
<?php $this->load->view('admin/_partials/head.php') ?>
</head>
<body>
<main class="main">
<?php $this->load->view('admin/_partials/side_nav.php') ?>
<div class="content">
<h1>Upload Avatar</h1>
<form action="" method="POST" enctype="multipart/form-data">
<div>
<label for="avatar">Pilih Gambar Avatar</label>
<input type="file" name="avatar" id="avatar" accept="image/png, image/jpeg, image/jpg, image/gif">
</div>
<?php if (isset($error)) : ?>
<div class="invalid-feedback"><?= $error ?></div>
<?php endif; ?>
<div>
<button type="submit" name="save" class="button button-primary">Upload</button>
</div>
</form>
<?php $this->load->view('admin/_partials/footer.php') ?>
</div>
</main>
</body>
</html>
Pada view ini kita menggunakan form dengan enctype="multipart/form-data"
ini adalah tipe enkripsi untuk upload file.
Berikut ini tampilannya:
Mari kita coba lakukan upload!
4. Percobaan
Percobaan tidak mengisi file:
Cobalah lakukan upload, tanpa mengisi input file. Maka hasilnya akan error seperti ini:
Percobaan upload file yang bukan gambar:
Percobaan upload file yang melewati batas ukuran:
Percobaan upload file yang berhasil:
Jika upload kita berhasil, maka akan ada file baru di dalam folder upload/avatar
.
..dan di dashboard pun akan ditampilkan.
Mantap 👍
Kini user sudah bisa mengubah avatarnya.
Lalu gimana kalau mau hapus avatar?
Fitur ini belum kita buat.
Karena itu, silakan lanjut!
🧑💻 Latihan: Fitur untuk Menghapus Avatar
Ubahlah method remove_avatar()
pada controller admin/Setting.php
menjadi seperti ini:
public function remove_avatar()
{
$current_user = $this->auth_model->current_user();
$this->load->model('profile_model');
// hapus file
unlink(FCPATH."/upload/avatar/".$current_user->avatar);
// set avatar menjadi null
$new_data = [
'id' => $current_user->id,
'avatar' => null,
];
if ($this->profile_model->update($new_data)) {
$this->session->set_flashdata('message', 'Avatar dihapus!');
redirect(site_url('admin/setting'));
}
}
Pada method ini, kita menghapus file avatar dengan fungsi unlink()
. Fungsi ini merupakan fungsi bawaan PHP untuk menghapus file.
Kemudian, kita set ulang nilai avatar
menjadi null
.
Mari kita coba lihat hasilnya:
Yap berhasil..
Tapi ada satu lagi masalah:
Saat user meng-upload file dengan format yang berbeda, file yang tidak tercatat di kolom avatar tidak akan terhapus.
Misalnya gini:
Saat ganti avatar, user meng-upload format jpg
. Kemudian dia upload lagi file dengan format png
. Maka akan ada dua file di dalam folder upload/avatar
.
Nah yang akan dicatat di database adalah yang terakhir, yakni png
.
Jika kita melakukan remove avatar, maka yang akan dihapus adalah avatar yang png
.
Sementara yang jpg
akan tetap berada di folder upload/avatar
.
Lalu gimana solusinya?
Solusinya:
Kita bisa menghapus semua file berdasarkan id user, tanpa mempedulikan formatnya. Kita bisa ikuti nama file seperti saat melakukan proses upload.
Contoh fungsinya seperti ini:
array_map('unlink', glob(FCPATH."/upload/avatar/$file_name.*"));
Fungsi glob()
merupakan fungsi untuk membaca file dengan pola tertentu. Fungsi ini akan menghasilkan sebuah array yang berisi list nama file.
Variabel $file_name
berisi id dari user yang sedang login. Ini sama seperti nama file saat kita melakukan upload.
Fungsi array_map
merupakan fungsi untuk melakukan mapping fungsi terhadap array. Artinya, fungsi akan dijalankan untuk semua item di dalam array.
Pada fungsi di atas, kita melakukan mapping fungsi unlink
untuk semua nama file yang ada di dalam array dari fungsi glob()
Oke..
Mari kita terapkan dalam aplikasi.
Ubahlah method remove_avatar()
menjadi seperti ini:
public function remove_avatar()
{
$current_user = $this->auth_model->current_user();
$this->load->model('profile_model');
// hapus file
$file_name = str_replace('.', '', $current_user->id);
array_map('unlink', glob(FCPATH."/upload/avatar/$file_name.*"));
// set avatar menjadi null
$new_data = [
'id' => $current_user->id,
'avatar' => null,
];
if ($this->profile_model->update($new_data)) {
$this->session->set_flashdata('message', 'Avatar dihapus!');
redirect(site_url('admin/setting'));
}
}
Kemudian, silakan coba remove avatar.. maka semua avatar akan dihapus walaupun di sana ada lebih dari satu format yang berbeda.
Apa Selanjutnya?
Kita sudah berhasil membuat fitur ubah avatar untuk user. Sebenarnya masih ada yang perlu di-improve di fitur ini seperti:
Melakukan Crop Image sebelum Upload (di sisi client) atau bisa juga sesudah upload (di sisi server).
Untuk crop image di sisi client, bisa coba pakai Cropper.js dan untuk sisi server, bisa pakai Library Image Manipulation dari Codeigniter.
Tutorial selanjutnya:
Source code tutorial ini bisa di-download di Github: