nginx+uwsgi+python实现web图片缩放功能


说明:此教程并非本人原创,只是整合了一下,供大家学习,如有错误欢迎指正。

py脚本为heyuxiang大牛所写,我这边只是拿来使用,此人是公司上任运维,传说是个大歪歪,未见过本尊。在此表示感谢!!!


1.nginx安装(省略网上有很多教程)


2.uwsgi安装

2.1编译uWSGI

uWSGI下载地址:http://projects.unbit.it/downloads/

tar xzvf uwsgi-1.9.13.tar.gz

cp -rf uwsgi-1.9.13 /data/uwsgi

make -j 8

#或者使用python编译

python uwsgiconfig.py --build

如果报错

yum install -y python*


启动uwsgi

/data/uwsgi/uwsgi --xml /data/shells/img_convert/uwsgi_conf.xml


#uwsgi_conf.xml文件

[root@nginx ~]# cat /data/shells/img_convert/uwsgi_conf.xml

<uwsgi>

  <socket>/tmp/nginx_python.sock</socket>

  <master/>

  <workers>8</workers>

  <threads>2</threads>

  <daemonize>/tmp/uwsgi.log</daemonize>

</uwsgi>


3.相关配置文件

mkdir -p /data/shells/


3.1 nginx配置(下面只贴出location部分,其他略过,网上自己找)

cat /data/nginx/conf/migu/img01.conf

#img01.test.com配置

server {

    # 设置监听端口

    include /data/nginx/conf/migu/port.conf;

    server_name  img01.test.com;

 

    location / {

            if (!-f $request_filename) {

                rewrite "^/(.+)/(.+)_(RsT)_(\d+)x(\d+)\.(jpg|png|gif|JPG|PNG|GIF)$" /pic_convert.py?dir=$1&file=$2&type=$3&width=$4&height=$5&format=$6&root=$document_root last;

            }

            root   /data/content;

               } 


# 处理图片转换

    location ~ pic_convert\.py$ {

               include uwsgi_params;

               uwsgi_param UWSGI_FILE /data/shells/img_convert/pic_convert.py;

               uwsgi_param UWSGI_TOUCH_RELOAD /data/shells/img_convert/pic_convert.py;

               uwsgi_pass unix:///tmp/nginx_python.sock;

       }


               error_page   500 502 503 504  /50x.html;

               location = /50x.html {

               root   html;

       }

}


3.2 python脚本

[root@nginx ~]# cat /data/shells/img_convert/pic_convert.py

#!/usr/bin/python

#__*__coding:utf-8__*__

#

# author: He Yuxiang

# version: 0.0.1

#


from datetime import date

import uwsgi, logging, re, os, subprocess, string


# 配置日志

logging.basicConfig(format = '%(levelname)s:%(asctime)s:%(message)s', level = logging.DEBUG, filename = '/tmp/%s-nginx-py.log' % date.today())


# http请求响应函数

def application(env, start_response):

    logging.debug("进入application......")

    status, response_headers, response_body = getResponse(env["QUERY_STRING"])

    start_response(status, response_headers)

    return response_body


# 获得请求参数

def getParam(query_string):

    params = {}

    # 获得请求子目录

    r = re.search(r"dir=(.+)\&file", query_string)

    params["dir"] = r.group(1)

    # 获得请求文件名

    r = re.search(r"file=(.+)(\..+)\&type", query_string)

    params["file"] = r.group(1)

    # 获得请求文件的路径

    r = re.search(r"root=(.+)", query_string)

    params["root"] = "%s" % r.group(1)

    # 获得图片转换类型(1:RsT:图片大小缩放)

    r = re.search(r"type=(RsT)", query_string)

    params["type"] = r.group(1)

    # 获得图片宽度

    r = re.search(r"width=(\d+)", query_string)

    params["width"] = r.group(1)

    # 获得图片高度

    r = re.search(r"height=(\d+)", query_string)

    params["height"] = r.group(1)

    # 获得图片类型

    r = re.search(r"format=(png|jpg|gif|PNG|JPG|GIF)", query_string)

    params["format"] = string.lower(r.group(1))

    logging.debug("请求参数:%s" % params)

    return params


# 获得响应内容

def getResponse(query_string):

    params = getParam(query_string)

    status = ""

    response_header = []

    response_body = ""

    filePath = "%s/%s/%s.%s" % (params["root"], params["dir"], params["file"], params["format"])

    logging.debug("filePath is %s" % filePath)

    # 设置返回状态码

    if os.path.exists(filePath):

        logging.debug("File %s.%s exists" % (params["file"], params["format"]))

        status = "200 ok"

    else:

        logging.debug("File %s.%s not exists" % (params["file"], params["format"]))

        status = '404 not found'

    # 设置响应头和响应内容

    if os.path.exists(filePath):

        logging.debug("开始设置响应头和响应内容...")

        response_header = [('Content-Type', 'p_w_picpath/%s' % params["format"])]

        destPath="%s/%s/%s.%s_%s_%sx%s.%s" % (params["root"], params["dir"], params["file"], params["format"], params["type"], params["width"], params["height"], params["format"])

        logging.debug("destPath is %s" % destPath)

        if params["type"] == 'RsT':

            resize(filePath, destPath, 

                   params["width"], params["height"])

            f = open(destPath)

            response_body = response_body.join(f)

            f.close()

        else:

            response_header = [('Content-Type', 'text/html')]

            response_body = "目前暂时无此需求,如有疑问,请联系管理员..."

    else:

        response_header = [('Content-Type', 'text/html')]

        response_body = "404 not fount"

    return status, response_header, response_body


# resize图片

def resize(inputFile, outputFile, width, height):

    if os.path.exists(outputFile):

        return

    else:

        subprocess.call(["convert", inputFile, "-resize",

                         "%sx%s>" % (width, height), outputFile])

                         

4.测试

将test.jpg上传到/data/content/img

配置本机hosts


浏览器访问:http://img01.test.com/img/test.jpg看到为原始大小

缩小:http://img01.test.com/img/test.jpg_RsT_70x70.jpg