02 May 2009

Membuat Aplikasi Download dengan Java

Dalam beraktifitas di internet, kita sering melakukan kegiatan download atau upload. Download adalah suatu kegiatan internet dimana kita mengambil suatu file dari remote komputer untuk bisa disimpan ke dalam komputer kita.

Pada dasarnya ketika mendownload sebuah file dari sebuah remote komputer atau server, sebenarnya komputer kita membaca byte demi byte file yang menjadi sasaran untuk kita download. Kemudian setelah semua byte sudah selesai dibaca maka komputer kita akan membungkusnya menjadi sebuah file yang isinya sama persis dengan yang kita download.

Dengan konsep tadi mari kita coba untuk membuat sebuah percobaan kecil yang menerapkan semua langkah-langkah download, nantinya kita akan melengkapi langkah-langkah download ini dengan pengetahuan sederhana yang bisa kita cari dari konsep download tersebut.

Mari kita mulai menyusun langkah-langkah sederhana tsb:

  1. Identifikasi URL

Untuk mendownload sebuah file kita pasti memerlukan alamat URL yang jelas serta file path dari file yang ingin kita download. Contoh : http://www.wayofmuslim.com/ebook-islam/AlQuranDigital.zip ini artinya kita akan mendownload sebuah file yang bernama AlQuranDigital.zip dari remote komputer wayofmuslim.com dengan lokasi file ebook-islam/

  1. Ukuran dari File yang ingin kita download.

Setiap file yang ingin kita download, kita harus mengetahui ukurannya. Tujuan dari mengetahui ukuran sebuah file yang akan kita download adalah nantinya kita akan membandingkan ukuran byte yang sudah terbaca dan tersimpan dalam komputer kita dengan ukuran file yang ada pada remote komputer tersebut, sehingga kita bisa tahu apakah file tersebut corrupted atau tidak sebelum kita membungkusnya menjadi sebuah file ke dalam komputer kita.

  1. Content Type dari file yang ingin kita download.

Untuk yang ini sebenarnya sifatnya optional, kita bisa memakai konsep ini atau tidak, bukanlah sebuah masalah tapi mengetahui ContentType suatu file menjadi dasar utama komunikasi teknologi internet.

Sepertinya dari 3 konsep diatas kita bisa membuat sendiri sebuah aplikasi java yang mempunyai kemampuan untuk mendownload file dari sebuah remote komputer. Ya memang bisa, karena sebenarnya konsep download sebuah file dari sebuah remote komputer memang sesederhana itu.

Sekarang mari kita buktikan teori tersebut dengan menyusun skenario berdasarkan konsep di atas untuk membuat sebuah aplikasi download dengan bahasa pemrograman Java. Scenario yang akan kita buat sbb:

  1. Identifikasi URL

Memeriksa apakah URL yang di supply benar atau tidak, disini kita akan memakai class URL yang ada pada java

  1. URL Valid

Jika URL tersebut valid, maka langsung kita lakukan Http Connection ke URL tersebut untuk memeriksa apakah komputer kita terhubung dengan jaringan internet atau tidak. Jika URL tersebut tidak valid maka langsung kita exit saja aplikasinya.

  1. Mengidentifikasi Content Type

Jika Http Connection yang kita lakukan mempunyai hasil yang bagus artinya host atau remote komputer bisa kita hubungi, langkah selanjutnya adalah mengidentifikasi content-type dari file yang akan kita download. Pada percobaan ini kita batasi saja, jika Content Type tersebut adalah text/html, maka kita tidak perlu mendownloadnya. Kenapa demikian? Bisa saja terjadi Http Status 404 (File Not Found) pada suatu file yang ingin kita download, dan pastinya tidak penting bagi kita untuk mendownload sebuah halaman html yang isinya hanya informasi bahwa File yang ingin kita download ternyata tidak ada.

  1. Mengidentifikasi panjang byte dari file (Content Length)

Oleh karena nantinya kita akan membaca byte demi byte file yang akan kita download tersebut, maka sangat penting untuk menyimpan informasi panjang byte dari file yang ingin kita download ke dalam sebuah variabel. Dan nantinya informasi panjang byte ini juga bisa kita jadikan suatu bahan untuk membandingkan jumlah byte yang sudah tersimpan dalam komputer kita dengan ini jumlah byte yang ada pada remote komputer, untuk mengetahui apakah file yang sudah kita download corrupted atau tidak.

  1. Baca byte demi byte

Ini adalah langkah yang paling penting dalam percobaan kita kali ini. Aplikasi yang kita buat harus bisa membaca byte demi byte file yang ingin kita download dan kemudian hasil dari pembacaan tersebut kita masukkan ke dalam variabel data yang bertype data byte. Cara membacanya adalah dengan cara melakukan looping dari 0 hingga panjangnya byte yang memang tadi sudah kita masukkan kedalam variabel.

  1. Bandingkan file local dengan file remote

Langkah selanjutnya kita akan membandingkan jumlah byte yang sudah terbaca dengan jumlah byte yang sebelumnya sudah kita simpang ke dalam sebuah variabel. Jika jumlah byte keduanya tidak sama maka sudah bisa di pastikan bahwa file yang kita download pasti corrupted dan nantinya pasti tidak akan bisa kita gunakan.

  1. Membungkus byte yang terbaca

Setelah kita tahu persis bahwa jumlah byte yang terbaca sama dengan jumah byte yang ada pada remote komputer maka saatnya kita membungkusnya kedalam sebuah file. Kita buat gampang saja bahwa nama dari file yang akan menjadi pembungkus byte-byte yang sudah kita download ini sama dengan nama file yang yang kita download.

Dari scenario di atas kita bisa membuat sebuah aplikasi sederhana seperti terlihat pada source code berikut ini:

package org.mojo.download.agent;

import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLConnection;

/**
* Created by IntelliJ IDEA.
* User: Mojo
* Date: May 2, 2009
* Time: 11:39:49 AM
* To change this template use File | Settings | File Templates.
*/
public class SingleDownloadAgent {

public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage : java SingleDownloadAgent <URL>" );
return;
} else {
try {
doDownload(args[0]);
} catch (IOException e) {
System.err.println("Exception e");
}
}
}

public static void doDownload(String sURL) throws IOException {
URL u = null;
//try URL
try {
u = new URL(sURL);
} catch (MalformedURLException ex) {
System.err.println("Malformed URL : " + ex);
return;
}catch (IOException ex) {
System.err.println("An Error Occured : " + ex);
return;
}

//reading Connection
URLConnection uc = null;
try {
uc = u.openConnection();
//identifying connection
uc.connect();
} catch (IOException e) {
System.out.println("Cannot Connect: Please Check Connection");
return;
}

String contentType = uc.getContentType();
System.out.println("contentType :" + contentType);

int contentLength = uc.getContentLength();
if (contentType.startsWith("text/html") || contentLength == -1) {
throw new IOException("This is html file.");
}

//collecting byte in var data
InputStream raw = uc.getInputStream();
InputStream in = new BufferedInputStream(raw);
byte[] data = new byte[contentLength];
int bytesRead = 0;
int offset = 0;
while (offset < contentLength) {
bytesRead = in.read(data, offset, data.length - offset);
if (bytesRead == -1) break;
offset += bytesRead;
}
in.close();

//file corrupted
if (offset != contentLength) {
throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes --> File Corrupted…");
}

//writing byte data to a file
String filename = u.getFile();
filename = filename.substring(filename.lastIndexOf('/') + 1);
FileOutputStream fout = new FileOutputStream(filename);
fout.write(data);
fout.flush();
fout.close();
}
}

Dalam source-code tersebut kita punya dua method, yaitu method utama dari aplikasi ini dan method doDownload dengan String sURL sebagai parameternya. Mari kita bahas satu demi satu kode diatas:

Seperti biasa pada baris awal source code diatas berisi deklarasi dimana class ini terletak dalam package dan deklarasi kita mengimport kelas-kelas yang kita butuhkan nantinya. Kemudian pada main method kita memeriksa apakah parameterURL disupplai ketika aplikasi ini di panggil. Memang pada aplikasi ini kita mendesain bahwa jika kita ingin memakai aplikasi ini untuk mendownload suatu file maka kita harus mensuplai parameter URL yang ingin kita download.

package org.mojo.download.agent;

import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLConnection;

/**
* Created by IntelliJ IDEA.
* User: Mojo
* Date: May 2, 2009
* Time: 11:39:49 AM
* To change this template use File | Settings | File Templates.
*/
public class SingleDownloadAgent {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage : java SingleDownloadAgent <URL>" );
return;
} else {
try {
doDownload(args[0]);
} catch (IOException e) {
System.err.println("Exception e");
}
}
}
………
Pada method utama ini, terlihat jika parameter URL tidak disuplai maka aplikasi akan langsung kita hentikan setelah sebelumnya di print-out petunjuk penggunaan aplikasi ini. Dan jika parameter URL disuplai maka program langsung memanggil method doDownload dengan args[0] sebagai paramaternya.

Sekarang mari kita lihat method ke dua yaitu method doDownload:

………
public static void doDownload(String sURL) throws IOException {
URL u = null;
//try URL
try {
u = new URL(sURL);
} catch (MalformedURLException ex) {
System.err.println("Malformed URL : " + ex);
return;
}
catch (IOException ex) {
System.err.println("An Error Occured : " + ex);
return;
}
………
Pada baris-baris ini kita menjalankan skenario pertama yaitu memeriksa validasi URL, dan kita membungkusnya disini dalam blok try-catch. Kita meletakkannya dalam blok try-catch tidak lain karena mencegah error yang terjadi dan bisa mengetahui dimana sebanarnya error terjadi dalam validasi URL ini.
…………
//reading Connection
URLConnection uc = null;
try {
uc = u.openConnection();
//identifying connection
uc.connect();
} catch (IOException e) {
System.out.println("Cannot Connect: Please Check Connection");
return;
}

String contentType = uc.getContentType();
System.out.println("contentType :" + contentType);

int contentLength = uc.getContentLength();
if (contentType.startsWith("text/html") || contentLength == -1) {
throw new IOException("This is html file.");
}
…………
Setelah itu pada baris di atas kita mengecek koneksi ke host atau remote komputer dengan cara membungkusnya ke dalam blok try-catch, kemudian baris selanjutnya kita mencari tahu content-type dari file yang ingin kita download dan memasukkan informasi tersebut ke dalam sebuah variable string bernama contentType. Kemudian kita memeriksa panjang byte file yang ingin kita download tersebut dan memasukkannya ke dalama variable contentLength yang bertipe integer. Dan baris tersebut dilanjutkan dengan pencabangan jika file yang kita download ternyata bertipe type/html langsung kita hentikan saja aplikasinya.
    …………    
//collecting byte in var data
InputStream raw = uc.getInputStream();
InputStream in = new BufferedInputStream(raw);
byte[] data = new byte[contentLength];
int bytesRead = 0;
int offset = 0;
while (offset < contentLength) {
bytesRead = in.read(data, offset, data.length - offset);
if (bytesRead == -1) break;
offset += bytesRead;
}
in.close();

//file corrupted
if (offset != contentLength) {
throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes --> File Corrupted…");
}
…………
Pada baris di atas, kita melihat disinilah pembacaan byte demi byte dilakukan oleh aplikasi yang kita buat, dengan teknik membuka output-stream dan kemudian membaca output stream tersebut dengan cara me-looping byte dengan Content Length sebagai batasan loopingnya, dan kemudian memasukkannya untuk disimpan dalam variable data yang bertype byte. Setelah selesai looping output stream kita tutup dan kemudian kita buat perbandingan antara jumlah byte yang tersimpan dalam variabel offset dengan variable contentLength.
…………
//writing byte data to a file
String filename = u.getFile();
filename = filename.substring(filename.lastIndexOf('/') + 1);
FileOutputStream fout = new FileOutputStream(filename);
fout.write(data);
fout.flush();
fout.close();

}
…………
Dan inilah kode terakhir yang kita buat, pada kode ini kita membungkus byte-byte data yang kita kumpulkan dalam variabel data untuk dibungkus ke dalam sebuah file. Untuk penamaan file ini kita beri nama sesuai dengan nama file yang kita download saja.

Demikianlah percobaan dan pembahasan kita kali ini, masih banyak yang bisa kita kembangkan dari percobaan sederhana ini, kita bisa membuat GUI-nya misalnya, atau menambahkan animasi progress bar dan lain-lain. Silahkan kembangkan kembali konsep-konsep ini untuk sesuatu yang lebih sempurna lagi.



Semoga bermanfaat.

Menteng, 03 Maret 2009


Josescalia.

1 comment:

dendy said...

makasi atas informasinya mas yusuf..
salam kenal..