mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-11-08 06:18:21 +01:00
5b8d7dec54
Update get.lua to use the new callbacks. The old "code" module is now the "mime" module. Updated all modules that depended on it. Updated url.lua to use the new namespace scheme, and moved the escape and unescape functions that used to be in the code.lua module to it, since these are specific to urls. Updated the callback entries in the manual.
146 lines
3.8 KiB
Lua
146 lines
3.8 KiB
Lua
-----------------------------------------------------------------------------
|
|
-- Little program to download files from URLs
|
|
-- LuaSocket sample files
|
|
-- Author: Diego Nehab
|
|
-- RCS ID: $Id$
|
|
-----------------------------------------------------------------------------
|
|
-- formats a number of seconds into human readable form
|
|
function nicetime(s)
|
|
local l = "s"
|
|
if s > 60 then
|
|
s = s / 60
|
|
l = "m"
|
|
if s > 60 then
|
|
s = s / 60
|
|
l = "h"
|
|
if s > 24 then
|
|
s = s / 24
|
|
l = "d" -- hmmm
|
|
end
|
|
end
|
|
end
|
|
if l == "s" then return string.format("%2.0f%s", s, l)
|
|
else return string.format("%5.2f%s", s, l) end
|
|
end
|
|
|
|
-- formats a number of bytes into human readable form
|
|
function nicesize(b)
|
|
local l = "B"
|
|
if b > 1024 then
|
|
b = b / 1024
|
|
l = "KB"
|
|
if b > 1024 then
|
|
b = b / 1024
|
|
l = "MB"
|
|
if b > 1024 then
|
|
b = b / 1024
|
|
l = "GB" -- hmmm
|
|
end
|
|
end
|
|
end
|
|
return string.format("%7.2f%2s", b, l)
|
|
end
|
|
|
|
-- returns a string with the current state of the download
|
|
function gauge(got, delta, size)
|
|
local rate = got / delta
|
|
if size and size >= 1 then
|
|
return string.format("%s received, %s/s throughput, " ..
|
|
"%.0f%% done, %s remaining",
|
|
nicesize(got),
|
|
nicesize(rate),
|
|
100*got/size,
|
|
nicetime((size-got)/rate))
|
|
else
|
|
return string.format("%s received, %s/s throughput, %s elapsed",
|
|
nicesize(got),
|
|
nicesize(rate),
|
|
nicetime(delta))
|
|
end
|
|
end
|
|
|
|
-- creates a new instance of a receive_cb that saves to disk
|
|
-- kind of copied from luasocket's manual callback examples
|
|
function stats(size)
|
|
local start = socket.time()
|
|
local got = 0
|
|
return function(chunk)
|
|
-- elapsed time since start
|
|
local delta = socket.time() - start
|
|
if chunk then
|
|
-- total bytes received
|
|
got = got + string.len(chunk)
|
|
-- not enough time for estimate
|
|
if delta > 0.1 then
|
|
io.stderr:write("\r", gauge(got, delta, size))
|
|
io.stderr:flush()
|
|
end
|
|
return chunk
|
|
else
|
|
-- close up
|
|
io.stderr:write("\n")
|
|
return ""
|
|
end
|
|
end
|
|
end
|
|
|
|
-- downloads a file using the ftp protocol
|
|
function getbyftp(url, file)
|
|
local save = socket.callback.receive.file(file or io.stdout)
|
|
if file then
|
|
save = socket.callback.receive.chain(stats(gethttpsize(url)), save)
|
|
end
|
|
local err = socket.ftp.get_cb {
|
|
url = url,
|
|
content_cb = save,
|
|
type = "i"
|
|
}
|
|
if err then print(err) end
|
|
end
|
|
|
|
-- downloads a file using the http protocol
|
|
function getbyhttp(url, file)
|
|
local save = socket.callback.receive.file(file or io.stdout)
|
|
if file then
|
|
save = socket.callback.receive.chain(stats(gethttpsize(url)), save)
|
|
end
|
|
local response = socket.http.request_cb({url = url}, {body_cb = save})
|
|
if response.code ~= 200 then print(response.status or response.error) end
|
|
end
|
|
|
|
-- determines the size of a http file
|
|
function gethttpsize(url)
|
|
local response = socket.http.request {
|
|
method = "HEAD",
|
|
url = url
|
|
}
|
|
if response.code == 200 then
|
|
return tonumber(response.headers["content-length"])
|
|
end
|
|
end
|
|
|
|
-- determines the scheme
|
|
function getscheme(url)
|
|
-- this is an heuristic to solve a common invalid url poblem
|
|
if not string.find(url, "//") then url = "//" .. url end
|
|
local parsed = socket.url.parse(url, {scheme = "http"})
|
|
return parsed.scheme
|
|
end
|
|
|
|
-- gets a file either by http or ftp, saving as <name>
|
|
function get(url, name)
|
|
local fout = name and io.open(name, "wb")
|
|
local scheme = getscheme(url)
|
|
if scheme == "ftp" then getbyftp(url, fout)
|
|
elseif scheme == "http" then getbyhttp(url, fout)
|
|
else print("unknown scheme" .. scheme) end
|
|
if name then fout:close() end
|
|
end
|
|
|
|
-- main program
|
|
arg = arg or {}
|
|
if table.getn(arg) < 1 then
|
|
io.write("Usage:\n luasocket get.lua <remote-url> [<local-file>]\n")
|
|
os.exit(1)
|
|
else get(arg[1], arg[2]) end
|