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)