Mercurial > luasocket
comparison etc/get.lua @ 0:4b915342e2a8
LuaSocket 2.0.2 + CMake build description.
author | Eric Wing <ewing . public |-at-| gmail . com> |
---|---|
date | Tue, 26 Aug 2008 18:40:01 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4b915342e2a8 |
---|---|
1 ----------------------------------------------------------------------------- | |
2 -- Little program to download files from URLs | |
3 -- LuaSocket sample files | |
4 -- Author: Diego Nehab | |
5 -- RCS ID: $Id: get.lua,v 1.25 2007/03/12 04:08:40 diego Exp $ | |
6 ----------------------------------------------------------------------------- | |
7 local socket = require("socket") | |
8 local http = require("socket.http") | |
9 local ftp = require("socket.ftp") | |
10 local url = require("socket.url") | |
11 local ltn12 = require("ltn12") | |
12 | |
13 -- formats a number of seconds into human readable form | |
14 function nicetime(s) | |
15 local l = "s" | |
16 if s > 60 then | |
17 s = s / 60 | |
18 l = "m" | |
19 if s > 60 then | |
20 s = s / 60 | |
21 l = "h" | |
22 if s > 24 then | |
23 s = s / 24 | |
24 l = "d" -- hmmm | |
25 end | |
26 end | |
27 end | |
28 if l == "s" then return string.format("%5.0f%s", s, l) | |
29 else return string.format("%5.2f%s", s, l) end | |
30 end | |
31 | |
32 -- formats a number of bytes into human readable form | |
33 function nicesize(b) | |
34 local l = "B" | |
35 if b > 1024 then | |
36 b = b / 1024 | |
37 l = "KB" | |
38 if b > 1024 then | |
39 b = b / 1024 | |
40 l = "MB" | |
41 if b > 1024 then | |
42 b = b / 1024 | |
43 l = "GB" -- hmmm | |
44 end | |
45 end | |
46 end | |
47 return string.format("%7.2f%2s", b, l) | |
48 end | |
49 | |
50 -- returns a string with the current state of the download | |
51 local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining" | |
52 local elapsed_s = "%s received, %s/s throughput, %s elapsed " | |
53 function gauge(got, delta, size) | |
54 local rate = got / delta | |
55 if size and size >= 1 then | |
56 return string.format(remaining_s, nicesize(got), nicesize(rate), | |
57 100*got/size, nicetime((size-got)/rate)) | |
58 else | |
59 return string.format(elapsed_s, nicesize(got), | |
60 nicesize(rate), nicetime(delta)) | |
61 end | |
62 end | |
63 | |
64 -- creates a new instance of a receive_cb that saves to disk | |
65 -- kind of copied from luasocket's manual callback examples | |
66 function stats(size) | |
67 local start = socket.gettime() | |
68 local last = start | |
69 local got = 0 | |
70 return function(chunk) | |
71 -- elapsed time since start | |
72 local current = socket.gettime() | |
73 if chunk then | |
74 -- total bytes received | |
75 got = got + string.len(chunk) | |
76 -- not enough time for estimate | |
77 if current - last > 1 then | |
78 io.stderr:write("\r", gauge(got, current - start, size)) | |
79 io.stderr:flush() | |
80 last = current | |
81 end | |
82 else | |
83 -- close up | |
84 io.stderr:write("\r", gauge(got, current - start), "\n") | |
85 end | |
86 return chunk | |
87 end | |
88 end | |
89 | |
90 -- determines the size of a http file | |
91 function gethttpsize(u) | |
92 local r, c, h = http.request {method = "HEAD", url = u} | |
93 if c == 200 then | |
94 return tonumber(h["content-length"]) | |
95 end | |
96 end | |
97 | |
98 -- downloads a file using the http protocol | |
99 function getbyhttp(u, file) | |
100 local save = ltn12.sink.file(file or io.stdout) | |
101 -- only print feedback if output is not stdout | |
102 if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end | |
103 local r, c, h, s = http.request {url = u, sink = save } | |
104 if c ~= 200 then io.stderr:write(s or c, "\n") end | |
105 end | |
106 | |
107 -- downloads a file using the ftp protocol | |
108 function getbyftp(u, file) | |
109 local save = ltn12.sink.file(file or io.stdout) | |
110 -- only print feedback if output is not stdout | |
111 -- and we don't know how big the file is | |
112 if file then save = ltn12.sink.chain(stats(), save) end | |
113 local gett = url.parse(u) | |
114 gett.sink = save | |
115 gett.type = "i" | |
116 local ret, err = ftp.get(gett) | |
117 if err then print(err) end | |
118 end | |
119 | |
120 -- determines the scheme | |
121 function getscheme(u) | |
122 -- this is an heuristic to solve a common invalid url poblem | |
123 if not string.find(u, "//") then u = "//" .. u end | |
124 local parsed = url.parse(u, {scheme = "http"}) | |
125 return parsed.scheme | |
126 end | |
127 | |
128 -- gets a file either by http or ftp, saving as <name> | |
129 function get(u, name) | |
130 local fout = name and io.open(name, "wb") | |
131 local scheme = getscheme(u) | |
132 if scheme == "ftp" then getbyftp(u, fout) | |
133 elseif scheme == "http" then getbyhttp(u, fout) | |
134 else print("unknown scheme" .. scheme) end | |
135 end | |
136 | |
137 -- main program | |
138 arg = arg or {} | |
139 if table.getn(arg) < 1 then | |
140 io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n") | |
141 os.exit(1) | |
142 else get(arg[1], arg[2]) end |