29 June 2008

Menangani File Upload dengan JSP

Pada aplikasi web, terkadang kita membutuhkan suatu interface yang bisa digunakan user untuk mengupload file ke server. File upload adalah kegiatan menambah atau menyalin file ke dalam suatu system komputer dengan cara memindahkan file yang lokasinya di komputer lokal ke komputer remote. File upload sering kali kita jumpai dalam suatu aplikasi web. Sebagai contohnya aplikasi web-mail, menggunakan file upload sebagai cara untuk melampirkan lampiran/attachment ketika user yang mempunyai account dalam web-mail tersebut ingin mengirimkan email dengan attachment.
Pada aplikasi web berbasis java, file upload mempunyai perlakuan tersendiri dalam prosesnya. Sebab, pada konsepnya file upload mempunyai proses yang lumayan rumit. Meskipun sudah banyak pustaka/library java yang mempermudah kita untuk membuat mekanisme file upload, namun tidak sedikit juga programmer yang membuat mekanisme file upload dengan caranya sendiri.
Kali ini kita akan mencoba menangani file upload pada aplikasi java. Kita akan mencobanya di dalam rangkaian file-file jsp, agar kita lebih mudah memahaminya. Kita juga akan menggunakan pustaka/library java yang menurut saya mudah untuk diimplementasikan di dalam contoh aplikasi web kita kali ini. Nama library tsb adalah common-file-upload yang di-release oleh Apache Foundation dalam rangkaian jakarta-common project mereka. Silahkan download library common-file-upload disini. Selain itu kita juga membutuhkan library yang lain yaitu common-io juga dari rangkaian jakarta-common, silahkan download filenya disini.
Kita langsung saja ke skenario file-upload ini:
  1. User membuka sebuah form pada aplikasi web kita dan disana ada suatu field/kolom yang memintanya untuk mengupload sebuah file.
  2. File yang diupload akan ditangani oleh sebuah process file upload yang nantinya file yang diupload ini akan diletakkan dalam suatu folder dalam aplikasi web kita yang kita beri nama /file_uploaded
  3. /file_uploaded ini terletak dalam {app-serv}/webapps/{appl-context}/ dimana {app-serv} adalah folder instalasi application server(Tomcat, Jboss, Glassfish, dll) dan {app-context} adalah folder instalasi aplikasi web kita kali ini.
Nantinya silahkan anda mencoba untuk meletakkan file upload bukan ke dalam folder yang ada dalam app-context melainkan di dalam folder di luar instalasi {app-serv} anda.
Berdasarkan skenario diatas berarti kita akan membutuhkan sebuah form dengan format html biasa dengan enc-type-nya adalah multipart/form-data. Kenapa harus multipart/form-data? Karena form jenis ini yang mampu membawa data yang bukan hanya berupa character tapi juga mampu membawa data yang berupa file. Dalam prosesnya sebenarnya form ini akan mengubah file yang diupload menjadi sebuah kumpulan byte-stream yang nantinya akan dibawa melalui port TCP/IP.
Sayang blog ini tidak mengijinkan kita untuk menulis kode-kode html, jadi silahkan anda download saja source project-nya disini. Setelah anda download, mari kita bahas file form_upload.html ini. Dapat kita lihat bahwa pada baris ke-8 pada file form_upload.html terdapat kalimat enctype=”multipart/form-data”, inilah yang membedakan form ini dengan form html standar yang biasa, bentuk form seperti inilah yang mampu membawa file masuk ke dalam komputer remote/server.
Pada baris itu kita juga melihat bahwa file selanjutnya adalah untuk memproses file upload adalah process_upload.jsp. File inilah yang bertugas untuk menerima file upload kiriman dari form_upload.html dan kemudian memproses file yang diupload dan meletakkannnya kedalam folder yang ditentukan.
Sekarang mari kita lihat potongan kode yang ada pada file process_upload.jsp:


<%@ page import="org.apache.commons.fileupload.FileItem" %>
<%@ page import="org.apache.commons.fileupload.FileUpload"%>
<%@ page import="java.io.File" %>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.util.List" %>
<%
String test="";
File savedFile = null;
boolean isMultipart = FileUpload.isMultipartContent(request);
if (!isMultipart) {
System.out.println(" Form Bukan Multipart...!!!");
return;
}
DiskFileUpload upload = new DiskFileUpload();
List items = null;
try {
items = upload.parseRequest(request);
} catch (Exception e) {
System.out.println("Exception = " + e.getMessage());
}

Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if (item.isFormField()){
test = request.getParameter("test");
}else{
File fullFile = new File(item.getName());
System.out.println("File Lengkap : " + fullFile);

String sPath = getServletConfig().getServletContext().getRealPath("/file_uploaded");
System.out.println("Lokasi penyimpanan file =" + sPath);

File savedFile = new File(sPath, fullFile.getName());

try {
item.write(savedFile);
} catch (Exception e) {
System.out.println("Ada Kesalahan ketika menyimpan File :" + e.getMessage());
}
}
}
%>

mari kita bahas kode-kode diatas:
<%@ page import="org.apache.commons.fileupload.DiskFileUpload" %>
<%@ page import="org.apache.commons.fileupload.FileItem" %>
<%@ page import="org.apache.commons.fileupload.FileUpload" %>
<%@ page import="java.io.File" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.util.List" %>
Baris ini adalah baris dimana ini adalah caranya jsp mengimport kelas-kelas yang dibutuhkan oleh kode-kode java dibawahnya nanti. Dalam baris ini kita dapat melihat library common-file-upload milik apache di-import, juga ada baris untuk mengimport kelas-kelas java yang lain disana diantaranya adalah : java.io.File, java.util.Iterator, dan java.util.List.
Kemudian baris selanjutnya adalah:
String test="";
File savedFile = null;
boolean isMultipart = FileUpload.isMultipartContent(request);
if (!isMultipart) {
System.out.println(" Form Bukan Multipart...!!!");
return;
}
Pada baris ini kita dapat melihat bahwa ada variable test yang ber-tipe String, savedFile yang bertipe File, dan isMutipart ber-type boolean yang langsung di inisialisasi untuk memeriksa apakah form pengirim termasuk type multipart/form-data atau bukan. Jika form pengirim bukan form multipart maka langsung saja diakhiri prosesnya dengan menambahkan kode return; setelah mem-print-out informasi bahwa form pengirim bukanlah multipart.
Jika form pengirim adalah form yang enctype-nya adalah multipart maka akan di teruskan dengan kode :

DiskFileUpload upload = new DiskFileUpload();
List items = null;
try {
items = upload.parseRequest(request);
} catch (Exception e) {
System.out.println("Exception = " + e.getMessage());
}
Pada baris ini ada object baru di instansiasi yaitu object DiskFileUpload dengan variablenya bernama upload. Lalu juga ada deklarasi variabel lain yaitu items dengan type datanya List namun variable ini di isi dengan nilai null. Kemudian baris selanjutnya ada blok try-catch, dengan statement mencoba memparsing request yang dikirimkan oleh form pengirim dan kemudian memasukkannya ke dalam variable items yang sudah di deklarasikan sebelumnya. Jika gagal memparsing request dari form pengirim maka akan di cetak Exception yang terjadi.
Kemudian pada baris selanjutnya adalah:

Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if (item.isFormField()){
test = request.getParameter("test");
}else{
File fullFile = new File(item.getName());
System.out.println("File Lengkap : " + fullFile);

String sPath = getServletConfig().getServletContext().getRealPath("/file_uploaded");
System.out.println("Lokasi penyimpanan file =" + sPath);

savedFile = new File(sPath, fullFile.getName());

try {
item.write(savedFile);
} catch (Exception e) {
System.out.println("Ada Kesalahan ketika menyimpan File :" + e.getMessage());
}
}
}

Ok, ini bagian yang agak sulit untuk dijelaskan, tapi mari kita coba untuk menjelaskannya. Pada baris pertama ada inisialisasi object Iterator dengan variabel itr yang langsung diisi nilainya dengan cara meng-iterate variabel items kedalam variable item yang bertype FileItem dan sudah selesai di parsing. Kemudian variabel item ini diperiksa, jika item adalah field form maka variabel test yang sudah di deklarasikan diatas diisi nilainya dengan inputan dari form pengirim yang bukan berupa file.
Sebaliknya jika item bukanlah field form maka langsung saja di asumsikan bahwa item tsb adalah file yang akan di upload. Lalu langsung saja kita ambil file tersebut dengan cara membuat object File baru dengan nama fullFile dan mengisinya dengan mengambil nama item tersebut. Selanjutanya kita coba print-out untuk mengetahui file apa yang dikirim oleh form.
Kemudian kita membuat sebuah variabel baru disini bernama sPath dengan type data String. Variabel ini dibuat dengan tujuan untuk mengambil dilokasi mana file upload akan disimpan. Pada baris ini kita dapat melihat bahwa file akan disimpan didalam folder bernama file_uploaded yang terletak didalam folder instalasi aplikasi web kita. Setelah kita tentukan dimana kita akan menyimpan file hasil upload itu, selanjutnya kita akan melakukan proses penyimpanan file yang telah diupload.
Baris berikutnya ada variable object bertype File dengan nama savedFile yang sudah kita deklarasikan sebelumnya, variabel object ini diisi nilainya dengan cara membuat object File baru yang disusun berdasarkan letak lokasi file(sPath) dan nama filenya fullFile.getName(). Setelah object baru ini dibuat maka kita coba menulis file baru yang sudah jadi ini dengan memanggil metode write yang dimiliki oleh variabel item yang bertype FileItem. Dengan tidak lupa meletakkannya di dalam blok try-catch untuk menangkap kesalahan jika ada file yang tidak bisa disimpan.
Untuk mencoba source yang mungkin sudah anda download, caranya adalah dengan mengkopi seluruh isi source project ke dalam {app-serv}/webapps/ anda. Dimana {app-serv} adalah folder dimana Application Server atau Servlet Container anda seperti Tomcat di install. Tidak perlu melakukan compile disini, sebab source filenya hanya berisi jsp dan library yang dibutuhkan saja. File-file source project ini sengaja diletakkan sudah tersusun dalam susunan yang benar sehingga anda tinggal meng-copynya saja dalam webapps anda dan kemudian tinggal me-restart Application Server/Servlet Container anda.
Terima kasih, Selamat Mencoba.

Semoga bermanfaat

Josescalia
Menteng 29 Juni 2008

16 comments:

Anonymous said...

hmmm mau nanya neh mas...terima kasih sebelumnya atas informasinya namun pada source code tersebut diatas nilai dari parameter untuk mengambil dari form field tidak ada nilainya atau bernilai null...hal ini menurut asumsi saya dikarenakan tipe formny yg memakai enctype itu...namun untuk proses file uploadnya sudah bisa dilakukan hanya saja passing parameter untuk form field tidak dikenali..Bagaimana solusinya?Terima kasih

JoseScalia said...

Terima kasih telah mengunjungi blog ini
Pembahasan artikel ini memang lebih kepada menangani file upload, jadi proses upload filenya yang lebih ditekankan.
Untuk masalah form field yang null atau tidak ada nilainya, semua tergantung pada formnya itu sendiri. pada code contoh ada baris yang seperti ini

if (item.isFormField()){
test = request.getParameter("test");



kode tersebut berusaha membaca inputan dari form jika ada suatu field (textbox, textarea,etc) yang diberi nama test dalam form feedernya, maka akan di masukkan nilainya ke dalam variable test.
Jika memang field dalam form feeder tidak ada, maka pastinya variabel test tidak akan terisi nilainya. atau null.
Sementara untuk pemakaian type form enctype, memang ini adalah standar sebuah form html jika kita ingin membuat sebuah form yang mampu mengupload file.
Intinya, paramater form field yang null atau tidak ada isinya, tidak berhubungan dengan masalah type formnya. itu hanya masalah apakah memang ada field test pada form feedernya atau tidak.
Untuk mengatasi Exception NullPointer pada sebuah mekanisme form submit, memang ada beberapa trick dalam jsp, mungkin di lain waktu akan kita bahas nanti..

Terima kasih
josescalia

Anonymous said...

saya juga mau nanya nih mas, kalo wkatu pake fileupload, misalkan saya pake commons fileupload-nya apache, kalo nama filenya dibuat variabel string misalkan namaFile. Giamana ya biar halaman program (.jsp ) lainnya tahu kalo barusan ngupload dengan nama file apa? atau gampangnya program di .jsp lain tahu isi dari variabel .jsp nya. Bagiaman ya mas? Terima kasih

JoseScalia said...

TO Anonymous:
Terima kasih telah mengunjungi Blog ini..Mungkin begini:
1. String nama file disimpan dalam session jsp, kemudian file jsp lain membaca value dari session yang sudah diisi dengan variable nama file tadi.
2. bisa juga dengan meredirect ke file jsp lain. namun pada saat meredirect string nama filenya juga di ikutsertakan ke dalam proses redirectionnya


Terima kasih
josecalia

Anonymous said...

Tapi mas gimana ya untuk nyimpen string nama file ke session soalnya saya pake applet untuk ngirim datanya? apa bisa mas

JoseScalia said...

TO: Anonymous...
Terima kasih sekali lagi telah mengunjungi blog ini kembaliBerarti pertanyaannya seputar komunikasi antara Applet dan Servlet yah...?
Mungkin link ini bisa membantu anda...
http://www.j-nine.com/pubs/applet2servlet/index.htm

Anonymous said...

sy br bgt bljr JEE. Sy sdh download file yg ada di halaman anda. tp sy jalanin file hmtlnya gk da pengaruh terhadap folder file_uploaded. cara pakainya gimana ya?

Anonymous said...

Terima kasih nech tutorialnya bagus sekali..tapi saya mau tanya saya sudah upload file dan berhasil..uploadnya ke server di linux.. dan saya lihat filenya di linux ada..tapi ketika saya ingin panggil melalui browser kenapa tidak ketemu yach..padahal file nya sudah ada..pathnya sudah benar..di lokasi foldernya itu jg ada beberapa file yg lain yg dimasukkan secara manual..
dan bisa terpanggil..tp kenapa file yg di upload melalui jsp saya tidak bisa terpanggil..

mohon pencerahannya..

Anonymous said...

org.apache.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 12 in the jsp file: /up.jsp
DiskFileUpload cannot be resolved to a type
\\\-------------------
padahal file comon upload sudah saya masukan di comon/lib sama di letak folder kerja webinf/lib

JoseScalia said...

ASK:
Terima kasih nech tutorialnya bagus sekali..tapi saya mau tanya saya sudah upload file dan berhasil..uploadnya ke server di linux.. dan saya lihat filenya di linux ada..tapi ketika saya ingin panggil melalui browser kenapa tidak ketemu yach..padahal file nya sudah ada..pathnya sudah benar..di lokasi foldernya itu jg ada beberapa file yg lain yg dimasukkan secara manual..
dan bisa terpanggil..tp kenapa file yg di upload melalui jsp saya tidak bisa terpanggil..

mohon pencerahannya..
===================================
Coba diperiksa lagi hak akses dari file tsb di linux, kalo protected, berarti ada yang harus di modifikasi sedikit pada form-upload.jspnya...

saya akui turorial ini memang cuma untuk file-upload ke server saja, dan tidak untuk didownload kembali lewat public akses..


###################################
ASK :
org.apache.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 12 in the jsp file: /up.jsp
DiskFileUpload cannot be resolved to a type
\\\-------------------
padahal file comon upload sudah saya masukan di comon/lib sama di letak folder kerja webinf/lib
===================================

kalo dilihat dari errornya sih sepertinya..ada di file jsp form_upload,
Class untuk DiskFileUpload tidak terbaca oleh compiler jsp..spertinya class DiskFileUpload belum di import di header file jspnya :
<%@ page import="org.apache.commons.fileupload.FileUpload"%>


Terima kasih telah mengunjungi blog ini...

Josescalia

JoseScalia said...

Dear all semua pembaca yang membaca artikel ini..ada beberapa revisi dari code untuk membaca inputan test.getParamaters("test");

seharusnya code tersebut diatas di ganti dengan code dibawah ini :

String name = item.getFieldName();
String value = item.getString();
if(name.equals("test")){
test = value;
}
System.out.println("test " + test);


jadi mohon diabaikan untuk kode yang pertama dan bisa diganti dengan kode revisinya..
Harap maklum, Terima kasih telah mengunjungi blog ini...

Thanks

Josescalia

Anonymous said...

bagus sekali nech tutorialnya..
saya mau tanya di situ kan hasil uploadnya di simpan di komputer lokal..
bagaimana caranya agar hasil upload file itu di simpan ke komputer lain yg masih dlm 1 jaringan..

Thanx,

Anonymous said...

Thanks berat mas.. heheh

ramz hc said...

Terima kasih mas jagoan neyon :)

Anonymous said...

thx, ngebantu bgt :D

Ridho Hawali Fani said...

thanks you so much!
its work absolutely, thanks bro :)