lua 多线程文件下载器

首先弄个配置文件,这样就可以随时配置想要下载的文件和存储路径

Like this: // config.lua

local Config = {}
local Request =
{
	{
		host = "pic2.zhimg.com",
		port = 80,
		path = "/80/v2-fdad05ad3f2b8ff3f64a8440f31adf92_hd.jpg",
		save = "v2-fdad05ad3f2b8ff3f64a8440f31adf92_hd.jpg"
	},
	{
		host = "pic4.zhimg.com",
		port = 80,
		path = "/80/v2-f7e4a1d2ab3d791125b5c073b17a71c9_hd.jpg",
		save = "v2-f7e4a1d2ab3d791125b5c073b17a71c9_hd.jpg"
	},
	{
		host = "pic1.zhimg.com",
		port = 80,
		path = "/80/v2-3d769bced4b30df15ebfedef71a18e21_hd.jpg",
		save = "v2-3d769bced4b30df15ebfedef71a18e21_hd.jpg"
	}
}

Config.Request = Request

return Config

再来个多线程下载 // download.lua

local Socket = require("socket")

function async_receive(conn)
	local response,status,partial = conn:receive(2 ^ 10)
	if status == "timeout" then
		coroutine.yield(conn)
	end
	return response or partial,status
end

function download(host,file_name,port,handle)
	local port = port or 80
	local conn = assert(Socket.connect(host,port))
	local request = string.format("GET %s HTTP/1.1\r\nhost: %s\r\n\r\n",file_name,host)
	conn:send(request)
	conn:settimeout(0)
	local result = {}
	while true do
		local s,status = async_receive(conn)
		if status == "closed" then
			break
		end
		result[#result + 1] = s
	end
	if handle ~= nil then
		handle(table.concat(result))
	end
end

local tasks = {}
function get(host,file_name,port,handle)
	local port = port or 80
	local default_handle = function(result)
		io.write(result)
	end
	local co = coroutine.wrap(function ()
		local handle = handle or default_handle
		download(host,file_name,port,handle)
	end)
	table.insert(tasks,co)
end


function dispatch_task()
	local timeout = {}
	local i = 1
	while true do
		if tasks[i] == nil then
			if tasks[1] == nil then
				break
			end
			i = 1
			timeout = {}
		end
		local res = tasks[i]()
		if not res then
			table.remove(tasks,i)
		else
			i = i + 1
			timeout[#timeout + 1] = res
			if #timeout == #tasks then
				Socket.select(timeout)
			end
		end
	end
end
function create_save_handle(file_name)
	return function (result)
		local handle = io.open(file_name,"w")
		local content = string.match(result,".*\r\n.*\r\n\r\n(.*)")
		handle:write(content)
		handle:close()
	end
end
function config_req_index(t,k)
	if k == "host" then
		error("can't found host in config")
	end	
	if k == "port" then
		return 80
	end
	if k == "path" then
		return "/"
	end
	if k == "save" then
		return string.format("%s@%d",t.host,t.port)
	end
	error("not use")
end

function load_config()
	local Config = require("config")
	for _,req in pairs(Config.Request) do
		if type(req) ~= "table" then
			print("don't write useless information in config file")
		else
			setmetatable(req,{__index = config_req_index})
			get(req.host,req.path,req.port,create_save_handle(req.save))
		end
	end
end
load_config()
dispatch_task()

大功告成!当然还可以更好!

你可能感兴趣的:(Lua)