利用Lua脚本开发一个远程图片服务器文件目录整理接口

117 阅读2分钟

需求场景

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脚本语法

接口虽然简单,主要知识点、功能点如下:

  1. lua客户端IP限定;
  2. 安全考虑,设置了输入参数过滤,工作目录限定;
  3. 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错误。

海哥实操原创,希望能对您有借鉴意义~!