Java でファイルをダウンロードするクライアントを作るといろいろと面倒。
java.net.URLConnection#getContent は Object を返すみたいで、これの中身が実際はどんなオブジェクトなのかAPI リファレンスには書いてないみたい。instanceofで調べろみたいなことが書いてあるだけ。HttpURLConnectionのほうかそれとも開発者向けガイドページにでも書いてあるんだろうか……
Jakarta Commons HttpClient を試すとかしてみたこともあるけど、ちょっとしたダウンロードでもけっこう面倒そうなコードを書かなくちゃいけない。
とりあえず、JDK1.5標準ライブラリだけでできそうなダウンロードのサンプルコードを書いてみた。
タイムアウトだけは重要な気がしているので、指定できるようにしてある。
import java.io.*;
import java.net.*;
public class Downloader {
public static void main(String[] args) throws IOException {
Downloader d = new Downloader();
d.setConnectTimeout(5000); // 通信リンクを開くときのタイムアウト値5秒
d.setReadTimeout(5000); // 入力ストリームから読み取る際のタイムアウト値5秒
byte[] b = d.getContent("http://www.nilab.info/zurazure2/myimage/zurazure_kohaku.png");
FileOutputStream fos = new FileOutputStream("test.png");
fos.write(b);
fos.close();
}
private int connectTimeout = 0;
private int readTimeout = 0;
public void setConnectTimeout(int timeout){
connectTimeout = timeout;
}
public void setReadTimeout(int timeout){
readTimeout = timeout;
}
public byte[] getContent(String url) throws IOException {
URLConnection con = new URL(url).openConnection();
con.setConnectTimeout(connectTimeout); // require Java 5.0
con.setReadTimeout(readTimeout); // require Java 5.0
InputStream in = con.getInputStream();
byte[] content;
try{
content = toBytes(in);
}finally{
in.close();
}
return content;
// http header の情報も取得したくなったら、専用のクラスを作って返せばいいし
}
private static byte[] toBytes(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(in, out);
// out.close(); // ByteArrayOutputStream を閉じても、何も変化はありません。
return out.toByteArray();
}
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buff = new byte[256];
int len = in.read(buff);
while (len != -1){
out.write(buff, 0, len);
len = in.read(buff);
}
}
}
やっぱり Jakarta のライブラリのほうがよかったかも……
Ref. NI-Lab.'s ヅラッシュドット: Java 5.0 のネットワークタイムアウト設定方法
追記: 2007-09-08
機能追加版を書いた → HTTP経由でファイルをダウンロードする その2 (同時ダウンロード数制限版)
tags: zlashdot Java Java
Posted by NI-Lab. (@nilab)