Tutorial Upload File di Codeigniter

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 diupload;
  • 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 uploadnya berhasil dan FALSE jika uploadnya 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

Silahkan 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().

id user di tabel

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/';

Konstata 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 diupload 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 foldernya agar bisa upload file.

Ketik perintah berikut:

sudo chmod 777 -R /var/www/html/beritacoding/upload/avatar/

Setelah itu, silahkan 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 ecntype="multipart/form-data" ini adalah tipe enkripsi untuk upload file.

Berikut ini tampilannya:

view form upload

Mari kita coba lakukan upload!

4. Percobaan

Percobaan tidak mengisi file:

Cobalah lakukan upload, tanpa mengisi input file. Maka hasilnya akan error seperti ini:

error no file

Percobaan upload file yang bukan gambar:

error file not allowed

Percobaan upload file yang melewati batas ukuran:

error file melewati batas

Percobaan upload file yang berhasil:

Jika upload kita berhasil, maka akan ada file baru di dalam folder upload/avatar.

file terupload

..dan di dashboard pun akan ditampilkan.

avatar berhasil di-upload

Mantap 👍

Kini user sudah bisa mengubah avatarnya.

Lalu gimana kalau mau hapus avatar?

Fitur ini belum kita buat.

Karena itu, silahkan 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 mejadi null.

Mari kita coba lihat hasilnya:

Yap berhasil..

Tapi ada satu lagi masalah:

Saat user mengupload file dengan format yang berbeda, file yang tidak tercatat di kolom avatar tidak akan terhapus.

Misalnya gini:

Saat ganti avatar, user menguplaod foramt jpg. Kemudian dia upload lagi file dengan format png. Maka akan ada dua file di dalam folder upload/avatar.

file avatar format png dan jpg

Nah yang akan dicatat di database adalah yang terakhir, yakni png.

tabel kolom avatar

Jika kita melakukan remove avatar, maka yang akan dihapus adalah avatar yang png.

Sementara yang jpg akan tetap berada di folder upload/avatar.

file terupload

Lalu gimana solusinya?

Solusinya:

Kita bisa menghapus semua file berdasarkan id user, tanpa memperdulikan 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, silahkan 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 didownload di Github:

[🎁 Download Source Code]