zoukankan      html  css  js  c++  java
  • tornado+nginx上传视频文件

    [http://arloz.me/tornado/2014/06/27/uploadvideotornado.html]

    [NGINX REFRER: Nginx upload module]

    由于tornado通过表达上传的数据最大限制在100M,所以如果需要上传视屏文件的情况在需要通过其他方式实现, 此处采用nginx的nginx-upload-modulejQuery-File-Upload实现。

    1.编译安装nginx-upload-module

    • 下载nginx-1.5.8
    • 下载nginx-upload-module2.0
    • 由于nginx-upload-module不支持最新版的nginx,直接编译会出错,需要打补丁 davromaniak.txt
    tar xzf nginx-1.5.8
    tar xzf nginx_upload_module-2.0.12.tar.gz
    cd nginx_upload_moule-2.0.12
    patch ngx_http_upload_module.c davromaniak.txt
    cd ../nginx-1.5.8
    ./configure --add-module=../nginx_upload_moule-2.0.12
    make & sudo make install

    2.配置nginx的upload-module

    upstream tornadoserver{
        server 127.0.0.1:8001;
    }
    server {
    listen       8080;
    server_name  localhost;
    location / {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass http://tornadoserver;
    }
    client_max_body_size 4G;
    client_body_buffer_size 1024k;
    
    if ($host !~* ^(localhost) ) {
    }
    location = /uploads {
        if ($request_method = OPTIONS) {
            add_header Pragma no-cache;
            add_header X-Content-Type-Options nosniff;
    
            # Access control for CORS
            add_header Access-Control-Allow-Origin "http://localhost";
            add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
            add_header Access-Control-Allow-Headers "cache-control, content-range, accept,
                origin, session-id, content-disposition, x-requested-with, ctent-type,
                content-description, referer, user-agent";
            add_header Access-Control-Allow-Credentials "true";
            # 10 minute pre-flight approval
            add_header Access-Control-Max-Age 600;
            return 204;
        }
        if ($request_method = POST) {
            add_header Pragma no-cache;
            add_header X-Content-Type-Options nosniff;
            #add_header Cache-control "no-story, no-cache, must-revalidate";
    
            # Access control for CORS
            add_header Access-Control-Allow-Origin "http://localhost";
            add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
            add_header Access-Control-Allow-Headers "cache-control, content-range, accept,
                    origin, session-id, content-disposition, x-requested-with,
                    content-type, content-description, referer, user-agent";
            add_header Access-Control-Allow-Credentials "true";
            # 10 minute pre-flight approval
            add_header Access-Control-Max-Age 600;
    
            upload_set_form_field $upload_field_name.name "$upload_file_name";
            upload_set_form_field $upload_field_name.content_type "$upload_content_type";
            upload_set_form_field $upload_field_name.path "$upload_tmp_path";
    
            upload_pass_form_field "^X-Progress-ID$|^authenticity_token$";
            upload_cleanup 400 404 499 500-505;
        }
    
        upload_pass @fast_upload_endpoint;
    
        # {a..z} not usefull when use zsh
        # mkdir {1..9} {a..z} {A..Z}
        upload_store /tmp/uploads 1;
    
        # set permissions on the uploaded files
        upload_store_access user:rw group:rw all:r;
    }
    location @fast_upload_endpoint {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass_header 'Access-Control-Allow-Origin';
        proxy_pass http://tornadoserver;
    }
    }

    3.demo页面

    <!DOCTYPE HTML>
    <html>
    <head> <meta charset="utf-8">
        <title>jQuery File Upload Example</title>
        <style>
        .bar {
            height: 18px;
            background: green;
        }
    </style></head>
    <body>
        <input id="fileupload" type="file" name="files[]" data-url="uploads" multiple>
        <script src=""></script>
        <script src="/static/js/vendor/jquery.ui.widget.js"></script>
        <script src="/static/js/jquery.iframe-transport.js"></script>
        <script src="/static/js/jquery.fileupload.js"></script>
        <script>
            $(function () {
                $('#fileupload').fileupload({
                    dataType: 'json',
                    done: function (e, data) {
                        $.each(data.result.files, function (index, file) {
                           $('<p/>').text(file.name+"  "+file.size).appendTo(document.body);
                        });
                    },
                    progressall: function (e, data) {
                        var progress = parseInt(data.loaded / data.total * 100, 10);
                        $('#progress .bar').css( 'width', progress + '%');
                    }
                });
            });
        </script>
        <div id="progress">
            <div class="bar" style=" 10%;"></div>
        </div>
    </body>
    </html>

    4.tornado处理

    当nginx的upload-module完成视频文件的传输之后,其会设置表单数据,并转发给后台tornado服务器处理。

    通过如下方式获得相关参数:

    name = self.get_argument("files[].name","")
    content_type = self.get_argument("files[].content_type","")
    oldpath = self.get_argument("files[].path","")
    size = os.path.getsize(oldpath)
    files = []
    files.append({"name":name,"type":content_type,"size":size})
    ret = {"files":files}
    self.write(tornado.escape.json_encode(ret))

    5.其它配置文件参考
    user root;
    worker_processes 1;
    
    #error_log logs/error.log;
    #error_log logs/error.log notice;
    #error_log logs/error.log info;
    
    #pid logs/nginx.pid;
    
    
    events {
    worker_connections 1024;
    }
    
    
    http {
    include mime.types;
    default_type application/octet-stream;
    
    #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    # '$status $body_bytes_sent "$http_referer" '
    # '"$http_user_agent" "$http_x_forwarded_for"';
    
    #access_log logs/access.log main;
    
    sendfile on;
    #tcp_nopush on;
    
    #keepalive_timeout 0;
    keepalive_timeout 65;
    
    #gzip on;
    
    server {
    upload_resumable on;
    client_max_body_size 100m;
    listen 8888;
    server_name localhost;
    # Upload form should be submitted to this location
    location /upload {
    # Pass altered request body to this location
    upload_pass @test;
    upload_store /tmp 1;
    
    upload_store_access user:r;
    
    upload_set_form_field $upload_field_name[name] "$upload_file_name";
    upload_set_form_field $upload_field_name[content_type] "$upload_content_type";
    upload_set_form_field $upload_field_name[path] "$upload_tmp_path";
    
    upload_aggregate_form_field "$upload_field_name[md5]" "$upload_file_md5";
    upload_aggregate_form_field "$upload_field_name[size]" "$upload_file_size";
    upload_pass_form_field "^submit$|^description$";
    upload_cleanup 400 404 499 500-505;
    }
    
    # Pass altered request body to a backend
    location @test {
    proxy_pass http://mongrel;
    }
    
    }
    
    server{
    listen 30091;
    root /var/www/sms/public/video;
    }
    
    upstream mongrel {
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;
    }
    
    server {
    upload_resumable on;
    client_max_body_size 100m;
    listen 3000;
    
    root /var/www/sms/public;
    access_log /var/www/sms/log/nginx.access.log;
    
    if (-f $document_root/system/maintenance.html) {
    rewrite ^(.*)$ /system/maintenance.html last;
    break;
    }
    
    #upload video
    location /upload_video {
    # Pass altered request body to this location
    upload_pass @rails;
    upload_store /tmp 1;
    
    upload_store_access user:r;
    
    upload_set_form_field $upload_field_name[name] "$upload_file_name";
    upload_set_form_field $upload_field_name[content_type] "$upload_content_type";
    upload_set_form_field $upload_field_name[path] "$upload_tmp_path";
    
    upload_aggregate_form_field "$upload_field_name[md5]" "$upload_file_md5";
    upload_aggregate_form_field "$upload_field_name[size]" "$upload_file_size";
    upload_pass_form_field "^submit$|^description$";
    upload_cleanup 400 404 499 500-505;
    }
    
    # Upload image
    location /upload_image {
    # Pass altered request body to this location
    upload_pass @rails;
    upload_store /tmp 1;
    
    upload_store_access user:r;
    
    upload_set_form_field $upload_field_name[name] "$upload_file_name";
    upload_set_form_field $upload_field_name[content_type] "$upload_content_type";
    upload_set_form_field $upload_field_name[path] "$upload_tmp_path";
    
    upload_aggregate_form_field "$upload_field_name[md5]" "$upload_file_md5";
    upload_aggregate_form_field "$upload_field_name[size]" "$upload_file_size";
    upload_pass_form_field "^submit$|^description$";
    upload_cleanup 400 404 499 500-505;
    }
    
    # Pass altered request body to a backend
    location @rails {
    proxy_pass http://mongrel;
    }
    
    location / {
    proxy_set_header X-Real-IP $remote_addr;
    
    # needed for HTTPS
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_max_temp_file_size 0;
    
    if (-f $request_filename) { 
    break; 
    }
    
    if (-f $request_filename/index.html) {
    rewrite (.*) $1/index.html break;
    }
    
    if (-f $request_filename.html) {
    rewrite (.*) $1.html break;
    }
    
    if (!-f $request_filename) {
    proxy_pass http://mongrel;
    break;
    }
    }
    
    error_page 500 502 503 504 /500.html;
    location = /500.html {
    root /var/www/sms/public;
    }
    }
    
    }
    

      

     
     
  • 相关阅读:
    POJ 1434 Fill the Cisterns! (模拟 or 二分)
    Educational Codeforces Round 16 D. Two Arithmetic Progressions (不互质中国剩余定理)
    Educational Codeforces Round 16 E. Generate a String (DP)
    UVALive 3958 Weird Numbers (负进制数)
    HDU 1429 胜利大逃亡(续) (bfs+状态压缩)
    svn 创建本地仓库
    android 动态库死机调试方法 .
    外部博客链接
    反汇编调试Android
    When a java class is load by classloader, where the constant poll be put?
  • 原文地址:https://www.cnblogs.com/apexchu/p/4261324.html
Copyright © 2011-2022 走看看