需求场景
Web端数据表有一个专门的附件图片库,记录了有效的图片,上传的临时文件也在/uploadfile/目录下面,只是没记录到表中,因此目录下面有太多孤立的临时垃圾,而远程有一台同步/uploadfile/目录的附件服务器,由于文件日积月累的将近几十G(含大量的垃圾),真正有效的文件可能不到一半。
现在需要整理目录,远程也要同步整理,因此使用Lua脚本为附件服务器写了一个接口,支持移动/拷贝两种模式。
Nginx服务器配置
附件服务器站点的Nginx中配置增加 ,
location ~ ^/(tocopy|tomove) {
default_type 'text/html';
charset utf-8;
content_by_lua_file conf/filecopy.lua;
break;
}
# 访问形式, 通过读取数据表得到源目,目标路径,带参数访问远程附件服务器:
# http://www.xxx.cn/tocopy?from=dirA/05/111.png&to=dirB/05/111.png
Lua脚本语法
接口虽然简单,主要知识点、功能点如下:
- lua客户端IP限定;
- 安全考虑,设置了输入参数过滤,工作目录限定;
- lua文件复制,lua多级目录自动创建;
-- 访问白名单,空格分割
local ip_ranges = "192.168.0.0 113.88.193.106 219.133.69.1 14.154.154.111";
fileLib={
-- 限制操作目录
path_base = "/www/wwwroot/uploadfile";
--作用:遍历创建子文件夹
--返回值:无
createSubFolder=function(path)
local path_tb={}
local new_path=""
-- 分割路径保存到table
for s in string.gmatch(path,"([^'/']+)") do
if s~=nil then
table.insert(path_tb,s)
end
end
for k,v in ipairs(path_tb) do
if k==1 then
new_path = fileLib.path_base.."/"..v
else
new_path=new_path.."/"..v
end
if os.execute("cd "..new_path) then
-- print(new_path.." exist")
else
os.execute("mkdir "..new_path)
-- return new_path.." do not exist"
end
end
end;
--作用:删除空文件夹/文件
--参数: folderPath——>需要删除的空文件夹/文件路径
--返回值:无
removeFile=function(folderPath)
os.remove(folderPath)
end;
--作用:判断文件是否存在
--返回值:true/false ——>是否存在
isFileExist=function(path)
f=io.open(path,"r")
return f~=nil and f:close();
end;
--作用:判断文件夹是否存在
--返回值:true/false ——>是否存在
isFolderExist=function (folderPath)
return os.execute("cd "..folderPath)
end;
copyFile=function(oldPath,newPath,isMove)
local oldIcon,errorString = io.open(oldPath,"rb")
assert(oldIcon~=nil , errorString)
local data = oldIcon:read("a")
oldIcon:close()
local newIcon = io.open(newPath,"wb")
newIcon:write(data)
newIcon:close()
if isMove==1 then
fileLib.removeFile(oldPath)
end
end;
respJson = function(cod, str)
local cjson = require "cjson"
local JSON = cjson.new()
local json = { code= cod, msg=str}
ngx.say(JSON.encode(json))
ngx.eof()
end;
}
--- ////////////////////////////////////////////
-- 检查IP是否在允许的IP段中
local client_ip = ngx.var.remote_addr;
local in_allowed_range = false
for whiteip in string.gmatch(ip_ranges, "[^%s]+") do
if ngx.re.find(client_ip, whiteip, "jo") then
in_allowed_range = true
break
end
end
if not in_allowed_range then
fileLib.respJson( 403,string.format("%s is forbidden",client_ip))
-- return ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- 获取args中的值,判断路径,安全过滤掉【../】
local pathfrom = string.gsub(ngx.var.arg_from,"%.%.%/","")
local pathto = string.gsub(ngx.var.arg_to,"%.%.%/","")
if pathfrom==pathto then
fileLib.respJson( 503,"pathto is the same as pathfrom")
end
pathfrom = fileLib.path_base.."/".. pathfrom
if not fileLib.isFileExist(pathfrom) then
fileLib.respJson( 503,string.format("Missing:%s", pathfrom))
else
-- ngx.say(string.format("From: %s <br>", pathfrom))
local topath =string.match(pathto, "(.+)/[^/]*%.%w+$")
-- ngx.say( string.format("Check【 %s 】<br>", fileLib.path_base.."/"..topath))
if not fileLib.isFolderExist(fileLib.path_base.."/"..topath) then
fileLib.createSubFolder(topath)
end
if ngx.var.uri=="/tomove" then
fileLib.copyFile(pathfrom, fileLib.path_base.."/"..pathto, 1)
fileLib.respJson(200, "Move success ")
else
if ngx.var.uri=="/tocopy" then
fileLib.copyFile(pathfrom, fileLib.path_base.."/"..pathto, 0)
fileLib.respJson(200, "Copy success")
else
fileLib.respJson(503, "Not config "..ngx.var.uri)
end
end
end
注意 filecopy.lua 放置的位置需要让nginx有权读取到,否则会出现404错误。
海哥实操原创,希望能对您有借鉴意义~!