トップLinux > curl/libcurl
curl/libcurl

1.はじめに

単独ファイルのダウンロードに関しては wget よりも curl の方がいい面があるようだ。 マイOSM地図システムとしては、最終的には libcurlライブラリを使う方がいいだろうが、 system関数で curlコマンドを実行する方法でもパフォーマンス上は問題なさそうである。

2.curlコマンドをsystem関数で実行する

最初に次のような使い方をした。-s は多分 silent に由来するものであろう。 -R はダウンロードしたファイルの更新時刻をサーバーに合わせるもの。多分、Remote に由来するものだろう。 --fail は確か、サーバーに該当ファイルがなかった場合などにエラーコードを返すものだったと思う。 これが system関数の戻り値になる。このコマンドでは pngファイルをダウンロードしているが、 pngファイルがなかった場合、エラー内容を示すテキストファイルがダウンロードされるため、 後からこれを削除している。 --create-dirs は 出力パス path に含まれるディレクトリがなかった場合、 これを作成せよというオプションである。-o はこの次が出力ファイル(パス名)であることを表す。

    sprintf(cmd, "curl -s -R --fail --create-dirs %s -o %s", url, path);
    if (system(cmd) != 0) {
        g_print("error %s\n", cmd);
        remove(path);
        continue;
    }

たった一行のコマンドでも libcurlを使ってプログラムで表すにはそれなりに手数がかかる。

3.ファイルの更新時刻をチェックする

ローカルにpathで指定したファイルが既にある場合、urlで指定したサーバ上のファイルがこれよりも 新しい場合にのみダウンロードしたい。

当初、-z オプションを付けるだけでその機能を果たしてくれることを期待したが、うまく行かなかった。

ファイル指定でもいいようなことがちらっと書かれているが詳しい情報が見つからない。

時刻指定については詳しい情報がある。色んな書式がサポートされている。

例えば 8/215/110.pngの更新時刻は2018/04/02 10:37:47である。 下の二つのコマンドを実行すると、上ではダウンロードが起きず、下ではダウンロードが起きることを確認した。

curl -R -z '20180402 10:38:00 JST' http://cyberjapandata.gsi.go.jp/xyz/std/8/215/110.png -o test.png
curl -R -z '20180402 10:36:00 JST' http://cyberjapandata.gsi.go.jp/xyz/std/8/215/110.png -o test.png

次のプログラムで得られる出力は Mon Apr 2 10:37:47 2018 JST である。

  struct st st;
  stat("./test.png", &st);
  time_t t = st.st_mtime;
  std::cout << std::put_time(std::localtime(&t), "%c %Z") << '\n';

念のため、以下の二つのコマンドを実行し、上ではダウンロードが起き、下ではダウンロードが起きないことを確認した。

地図システムではこの書式が一番楽なので、これを使うことにする。

curl -R -z 'Mon Apr  2 10:37:37 2018 JST' http://cyberjapandata.gsi.go.jp/xyz/std/8/215/110.png -o test.png
curl -R -z 'Mon Apr  2 10:37:57 2018 JST' http://cyberjapandata.gsi.go.jp/xyz/std/8/215/110.png -o test.png

A.リファレンス

[1] https://curl.haxx.se/libcurl/c/CURLOPT_TIMECONDITION.html
[2] curl_getdate(3)