标签 图片 下的文章

搭建图片服务(二)

图片写入Mongodb

所需软件

  • lua-resty-moongoo-master.zip
  • lua-cbson-master.zip
  • mongo-c-driver-1.7.0.tar.gz

依赖安装

  • 安装mongo-c-driver
  1. 解压mongo-c-driver-1.7.0.tar.gz
    tar -zxf mongo-c-driver-1.7.0.tar.gz
  2. 安装依赖
    yum install cyrus-sasl-devel
  3. 编译安装
    ./configure --enable-sasl=yes
    make && make install
  4. 链接库
    ln -s /usr/local/lib/libbson-1.0.so.0 /lib64/libbson-1.0.so.0
  • 安装lua-cbson
  1. 解压lua-cbson-master.zip

    unzip lua-cbson-master.zip

  2. 安装依赖

    yum install cmake gcc gcc-c++

  3. 编辑FindLuaJIT.cmake文件

   cd cmake
   vi FindLuaJIT.cmake
   在find_path和find_library加入/usr/local/luajit/ 
  1. 配置
    mkdir build && cd build && cmake ..

  2. 编译安装
    make && make install

  • 安装lua-resty-moongoo
  1. 解压lua-resty-moongoo-master.zip
    unzip lua-resty-moongoo-master.zip
  2. 安装
    cd lib && cp -R resty /usr/local/luajit/lib/lua/

上传脚本

  • mongo_write.lua
  • nginx_upload_for_mongodb.lua

修改nginx.conf

location /upload_to_mongodb {
    error_log logs/upload_err.log;
    content_by_lua_file lua_lib/nginx_upload_for_mongodb.lua;
}

重新载入

nginx -s reload

脚本内容

  • mongo_write.lua
local moongoo = require("resty.moongoo")
local cbson = require("cbson")

local _M = {}           -- 局部的变量
_M._VERSION = '1.0'     -- 模块版本
local mt = {__index = _M}

function _M:new(o,url,dbname)
    o = o or {}
    self.__index = self
    self.url = url
    self.dbname = dbname
    self.mg = nil
    setmetatable(o,self)
    return o
end

function _M:connection()
   local mg, err = moongoo.new(self.url)
   if not mg then
    error(err)
   end
   return mg
end

function _M:writeFile(filename,data,lng,lat)
   if self.mg == nil then
     self.mg = self:connection(self.url)
   end
   local gridfs = self.mg:db(self.dbname):gridfs()
   local fs = gridfs:create(filename,{filename=filename,date=os.date(),metadata={longitude=lng,latitude=lat}},false)
   fs:write(data)
   fs:close()
end

function _M:updateInfo(fns,metadata)
   if self.mg == nil then
     self.mg = self:connection(self.url)
   end
   local c = self.mg:db(self.dbname):collection("fs.files")
   for _,fn in ipairs(fns) do
      local fsFile = c:find_one({filename=fn})
      fsFile['metadata']= metadata
      c:update({filename=fn},fsFile)
   end
end

function _M:close()
   if self.mg ~= nil then
      self.mg:close()
   end
end

return _M

  • nginx_upload_for_mongodb.lua
string.split = function(line, sep)

    sep = sep or ' '
    local retval = {}
    local pos = 1
    while true do
        local from, to = string.find(line, sep, pos)
        if from then
            local item = string.sub(line, pos, from-1)
            table.insert( retval, item )
            pos = to + 1
        else
            local item = string.sub(line, pos)
            table.insert( retval, item )
            break
        end
    end
    return retval
end    

string.trim = function (s)
  return (s:gsub("^%s*(.-)%s*$", "%1"))
end

--获取扩展名  
function getExtension(filename)  
    return filename:match(".+%.(%w+)$")  
end

local stringy = require "stringy"
local resty_sha1 = require "resty.sha1"
local upload = require "resty.upload"
local cjson = require "cjson"
local chunk_size = 4096
local form = upload:new(chunk_size)
local sha1 = resty_sha1:new()
local file
local longitude='11111'
local latitude='22222'
local extnames={"png","jpg","jpeg","gif"}
local msg = {success=false,msg='上传失败',data=nil}


local mongo = require("mongo_write")
local mg = mongo:new(nil,"mongodb://user:password@ip:port/dbname?authMechanism=SCRAM-SHA-1",'dbname')

function extExists(ext)
    for _, value in pairs(extnames) do
        if value == ext then
            return true
        end
    end

    return false
end

local fileNames={}
local fileRes={}
local part_name, part_value
local params={}
local ids={}
while true do
    local typ, res, err = form:read()

    if not typ then
        ngx.say("failed to read: ", err)
        return
    end

    if typ == "header" then
        local key=res[1]
        local value=res[2]
        
        if stringy.startswith(string.lower(res[1]), "content-disposition") then
                local parts = stringy.split(res[3], ";")
                local current_parts = stringy.split(stringy.strip(parts[2]), "=")
                if string.lower(table.remove(current_parts, 1)) == "name" then
                    local current_value = stringy.strip(table.remove(current_parts, 1))
                    part_name = string.sub(current_value, 2, string.len(current_value) - 1)
                end
        end

        if key =="Content-Disposition" then
             local kvlist=string.split(value,';')

             for _, kv in ipairs(kvlist) do
                    local seg = string.trim(kv)
                    --ngx.log(ngx.ERR,seg)
                    if seg:find("filename") then
                        local kvfile = string.split(seg, "=")
                        filename = string.sub(kvfile[2], 2, -2)
                        if filename then
                            --获取文件后缀名字
                            fileExtension=getExtension(filename)
                            --ngx.log(ngx.ERR,fileExtension)
                            if extExists(fileExtension) == false then
                               msg['msg'] = '文件类型错误'
                               ngx.say(cjson.encode(msg))
                               return 1
                            end
                            local linuxTime=tostring(os.time())
                            local filename = linuxTime..filename
                            filePath= "/tmp/attachment/image/"..filename
                            file,errmsg = io.open(filePath, "w+")
                            --存储的文件路径                    
                            --ngx.say("failed to open file ", filePath)
                            if not file then
                                ngx.say("failed to open file ", filePath .. errmsg)
                                return 1
                            end
                            table.insert(fileNames,filename)
                        else
                            return 1
                        end
                        --跳出循环
                        break 
                    end
             end
        end
    elseif typ == "body" then
        if part_name ~= nil and part_name ~="" and part_name ~='file' then
                part_value = res
        end
        if file then
                table.insert(fileRes,res)
                file:write(res)
                sha1:update(res)
        end

    elseif typ == "part_end" then
        if part_name ~= nil and part_name ~="" and part_name ~='file' then
           params[part_name] = part_value

           -- Reset fields for the next part
           part_value = nil
           part_name = nil
        end

        if file then
           local filename = fileNames[#fileNames]
           --ngx.log(ngx.ERR,filename)   
           mg:writeFile(filename,table.concat(fileRes),longitude,latitude)
           fileRes = nil
           file:close()
           file = nil
        end
        local sha1_sum = sha1:final()
        sha1:reset()
        --my_save_sha1_sum(sha1_sum)
    elseif typ == "eof" then
        msg['success'] = true
        msg['msg'] = '上传成功'
        msg['data']= fileNames

        mg:updateInfo(fileNames,params)
                mg:close()
        ngx.say(cjson.encode(msg))
        fileNames = nil
        break

    else
        -- do nothing
    end
end