Upload berkas
NexaForm dan helper file untuk upload aman: validasi, setUpload(), thumbnail, dan praktik penyimpanan.
NexaForm · setUpload()
Pengenalan File Uploads
NexaForm menyediakan sistem yang komprehensif untuk menangani upload file dengan aman dan efisien. Dengan menggunakan NexaForm dan NexaFile helper, Anda dapat dengan mudah mengimplementasikan fitur upload file dalam aplikasi Anda, termasuk validasi, enkripsi nama file, pembuatan thumbnail, dan banyak lagi.
Konfigurasi Upload File
Untuk mengaktifkan upload file dalam form, Anda perlu mengatur konfigurasi upload dengan method setUpload():
$form = $this->createForm();
// Konfigurasi form dengan field file
$form->fields([
'title' => 'Title|5|Judul minimal 5 karakter',
'description' => 'Textarea|10|Deskripsi minimal 10 karakter',
'image' => 'File|jpg,png,gif|Gambar harus berupa JPG/PNG/GIF maksimal 2MB',
'document' => 'FileOptional|pdf,doc,docx|Dokumen maksimal 5MB'
])
->setUpload([
// Konfigurasi utama
'maxSize' => '5MB', // Ukuran maksimum file (dapat menggunakan format seperti '2MB', '1GB')
'allowedTypes' => ['jpg', 'png', 'gif', 'pdf', 'doc', 'docx'], // MIME types yang diizinkan
'allowedExtensions' => ['jpg', 'png', 'gif', 'pdf', 'doc', 'docx'], // Ekstensi file yang diizinkan
// Konfigurasi thumbnail (opsional)
'thumbnail' => ['300x200', '150x100'], // Ukuran thumbnail yang akan dibuat
'thumbnailCropMode' => 'fit' // Mode cropping: 'fit' (pertahankan rasio) atau 'crop' (isi kanvas)
]);YYYY/MM/) di dalam direktori upload dasar. Nama file juga secara otomatis dienkripsi untuk keamanan.
Validasi File
NexaForm menyediakan beberapa aturan validasi khusus untuk file:
file- Field harus berupa file yang diuploadfileoptional- Field boleh kosong atau berupa file yang diuploadimage- Field harus berupa file gambar (jpg, jpeg, png, gif)mimes:ext1,ext2,...- Field harus berupa file dengan ekstensi tertentumax:size- Ukuran file tidak boleh melebihi size (dalam KB atau dengan notasi seperti 2M, 1G)dimensions:min_width=100,min_height=100,max_width=1000,max_height=1000- Dimensi gambar harus sesuai
$form->fields([
// File gambar wajib, max 2MB, dimensi minimal 300x200
'profile_image' => 'File|jpg,png,gif|Dimensi gambar minimal 300x200',
// File PDF opsional, max 5MB
'resume' => 'FileOptional|pdf|File resume maksimal 5MB',
// File gambar atau dokumen, max 10MB
'attachment' => 'File|jpg,jpeg,png,pdf,doc,docx|File attachment maksimal 10MB'
]);Memproses Upload File
Saat form disubmit, NexaForm akan otomatis memproses upload file jika konfigurasi upload telah diatur:
public function uploadFile(): void
{
$form = $this->createForm();
// Konfigurasi form dengan field file
$form->fields([
'title' => 'Title|5|Judul minimal 5 karakter',
'image' => 'File|jpg,png,gif|Gambar maksimal 2MB'
])
->setUpload([
'maxSize' => '2MB',
'allowedTypes' => ['jpg', 'png', 'gif'],
'allowedExtensions' => ['jpg', 'png', 'gif'],
'thumbnail' => ['300x200', '150x100'],
'thumbnailCropMode' => 'fit'
]);
if ($this->isPost()) {
// Proses form
$result = $form->process();
if ($result['success']) {
// Form valid dan file berhasil diupload
$data = $result['data'];
// $data['image'] berisi path file yang diupload
$imagePath = $data['image'];
// Informasi file yang diupload
$fileInfo = $result['files']['image'];
// Simpan data ke database
$this->useModels('Article', 'save', [
'title' => $data['title'],
'image_path' => $imagePath,
'image_name' => $fileInfo['orig_name'] ?? $fileInfo['path'],
'image_type' => $fileInfo['type'],
'image_size' => $fileInfo['size']
]);
$this->setFlash('success', 'File berhasil diupload');
$this->redirect('/articles');
return;
}
}
// Render form dengan data validasi
$this->assignVars($form->Response());
$this->render('articles/upload');
}Hasil Upload File
Setelah file berhasil diupload, informasi file tersedia dalam array $result['files']:
// Struktur $result['files'] untuk field 'image'
[
'image' => [
'path' => '2023/05/encrypted_filename.jpg', // Path file relatif
'size' => '1.00 MB', // Ukuran file dalam format yang mudah dibaca
'type' => 'image/jpeg', // MIME type
'uploaded_at' => '2023-05-20 15:30:45', // Waktu upload
'thumbnails' => [ // Informasi thumbnail jika dikonfigurasi
'300x200' => '2023/05/300x200/encrypted_filename.jpg',
'150x100' => '2023/05/150x100/encrypted_filename.jpg'
]
]
]
Dalam data yang divalidasi ($result['data']), field file akan berisi path file yang diupload:
// Struktur $result['data'] untuk form dengan field file
[
'title' => 'My Article',
'image' => 'uploads/images/encrypted_filename.jpg' // Path file relatif
]Multiple File Uploads
Untuk mengupload multiple file, Anda dapat menggunakan array notation dalam nama field:
// HTML Form
<form method="post" enctype="multipart/form-data">
<input type="text" name="title">
<input type="file" name="images[]" multiple>
<button type="submit">Upload</button>
</form>
// Controller
public function uploadMultipleFiles(): void
{
$form = $this->createForm();
// Konfigurasi form dengan field file multiple
$form->fields([
'title' => 'Title|5|Judul minimal 5 karakter',
'images' => 'File|jpg,png,gif|Gambar maksimal 2MB' // Validasi untuk setiap file
])
->setUpload([
'maxSize' => '2MB',
'allowedTypes' => ['jpg', 'png', 'gif'],
'allowedExtensions' => ['jpg', 'png', 'gif'],
'thumbnail' => ['300x200', '150x100']
]);
if ($this->isPost()) {
// Proses form
$result = $form->process();
if ($result['success']) {
// Form valid dan file berhasil diupload
$data = $result['data'];
$title = $data['title'];
// Informasi file yang diupload
$files = $result['files']['images'];
// Simpan data ke database
foreach ($files as $file) {
$this->useModels('Gallery', 'save', [
'title' => $title,
'image_path' => $file['path'],
'image_name' => $file['orig_name'],
'image_type' => $file['file_type'],
'image_size' => $file['file_size']
]);
}
$this->setFlash('success', count($files) . ' file berhasil diupload');
$this->redirect('/gallery');
return;
}
}
// Render form
$this->assignVars($form->Response());
$this->render('gallery/upload');
}Menghapus File
NexaForm menyediakan method deleteFile() untuk menghapus file yang sudah diupload:
public function deleteImage(): void
{
$form = $this->createForm();
// Mendapatkan ID gambar dari parameter
$imageId = $this->getParam('id');
// Mendapatkan data gambar dari database
$image = $this->useModels('Gallery', 'getById', [$imageId]);
if (!$image) {
$this->setFlash('error', 'Gambar tidak ditemukan');
$this->redirect('/gallery');
return;
}
// Hapus file dari penyimpanan
$form->deleteFile($image['image_path']);
// Cek hasil penghapusan
$deleteResult = $form->getDeleteResult();
if ($deleteResult && $deleteResult['main_file']) {
// Hapus data dari database
$this->useModels('Gallery', 'delete', [$imageId]);
$this->setFlash('success', 'Gambar berhasil dihapus');
} else 'Gagal menghapus file'; $this->setFlash('error', $error);
$this->redirect('/gallery');
}
Method deleteFile() dapat menerima string path file atau array informasi file:
// Hapus file dengan path
$form->deleteFile('uploads/images/file.jpg');
// Hapus file dengan array informasi file
$form->deleteFile([
'path' => 'uploads/images/file.jpg',
'thumb_path' => 'uploads/images/file_thumb.jpg'
]);
// Mendapatkan hasil penghapusan
$deleteResult = $form->getDeleteResult();
// [
// 'main_file' => true, // Apakah file utama berhasil dihapus
// 'thumb_file' => true, // Apakah thumbnail berhasil dihapus
// 'errors' => [] // Array error jika ada
// ]
// Mendapatkan error penghapusan
$deleteError = $form->getDeleteError();Menampilkan File dalam Template
Untuk menampilkan file yang diupload dalam template, Anda dapat menggunakan informasi file yang disimpan:
public function viewGallery(): void
{
// Mendapatkan semua gambar dari database
$images = $this->useModels('Gallery', 'getAll');
// Assign data ke template
$this->assignVar('images', $images);
// Render template
$this->render('gallery/view');
}Di template, Anda dapat menampilkan gambar seperti ini:
<div class="gallery">
<!-- NEXA images -->
<div class="gallery-item">
<h3>{title}</h3>
<img src="/{image_path}" alt="{title}">
<p>Original: {image_name}</p>
<p>Size: {image_size} KB</p>
<a href="/gallery/delete/" class="btn btn-danger">Delete</a>
</div>
<!-- END images -->
</div>Menampilkan Preview File
Untuk menampilkan preview file yang dipilih sebelum diupload, Anda dapat menggunakan JavaScript:
<form method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="image">Image</label>
<input type="file" name="image" id="image" class="form-control-file" onchange="previewImage(this)">
<div id="image-preview" class="mt-2"></div>
{image_info}
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
<script>
function previewImage(input) {
const preview = document.getElementById('image-preview');
preview.innerHTML = '';
if (input.files && input.files[0]) {
const reader = new FileReader();
reader.onload = function(e) {
const img = document.createElement('img');
img.src = e.target.result;
img.style.maxWidth = '300px';
img.style.maxHeight = '200px';
img.className = 'img-thumbnail';
preview.appendChild(img);
}
reader.readAsDataURL(input.files[0]);
}
}
</script>Best Practices
Berikut adalah beberapa praktik terbaik dalam menangani upload file:
- Selalu validasi tipe file dan ukuran file untuk mencegah upload file berbahaya
- Gunakan
encrypt_nameuntuk mencegah overwrite file dan meningkatkan keamanan - Simpan informasi file original (nama, tipe, ukuran) di database
- Gunakan
create_thumbuntuk gambar yang akan ditampilkan di halaman web - Batasi ukuran file yang dapat diupload untuk mencegah server overload
- Implementasikan mekanisme pembersihan file yang tidak digunakan
- Gunakan direktori upload yang berbeda untuk jenis file yang berbeda
- Pastikan direktori upload memiliki permission yang tepat (writeable)
- Gunakan AJAX untuk upload file besar untuk pengalaman user yang lebih baik
Lanjut
Sebelumnya: Validasi form. Berikutnya: Keamanan form. Indeks Forms · Dokumentasi · Beranda.