drem1lin
@drem1lin
чуть программист, чуть чуть админ...

Как обрабатывать загрузку файла через GET и POST запросы?

Добрый день, возникла необходимость сделать сервер, принимающий файлы по GET и POST запросам и сохраняющий их в определенную папку, с нормальными именами. Есть реализация подобного сервера на python, но тут есть вопросы к производительности сервера и его надежности. Хочется сделать что-то такое на nginx или любом другом промышленном веб-сервере. Я правильно понимаю, что мне понадобится написать какой-то backend?
В общем я об этом ничего не знаю, и прошу направить меня на правильный путь раскопок. Я много всего прочитал, но ничего из прочитанного не сработало, а что-то очень устарело.
  • Вопрос задан
  • 303 просмотра
Решения вопроса 1
deepblack
@deepblack
Можно обойтись одним только nginx (используя lua-nginx-module):
nginx_upload.conf
pid        logs/nginx_upload.pid;
events {
    worker_connections  1024;
}

http {
    lua_package_path '/usr/local/lib/lua/5.1/?.lua;;';

    server {
        listen       8001;

        # download
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;

        # auth
        auth_basic "Restricted site";
        auth_basic_user_file /opt/nginx/.htpasswd;

        location /download {
            alias upload;
        }


        location ~ ^/upload_lua(/.*)?$ {
            set $store_path upload$1/;
            content_by_lua_file conf/lua/my_upload.lua;
        }

        location ~ ^/delete/(.*)$ {
            set $file_path upload/$1;
            content_by_lua_file conf/lua/my_delete.lua;
        }
    }
}

https://www.yanxurui.cc/posts/server/2017-03-21-NG...

my_upload.lua

local upload = require "resty.upload"

local function my_get_file_name(header)
    local file_name
    for i, ele in ipairs(header) do
        file_name = string.match(ele, 'filename="(.*)"')
        if file_name and file_name ~= '' then
            return file_name
        end
    end
    return nil
end

local chunk_size = 4096
local form = upload:new(chunk_size)
local file
local file_path
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 file_name = my_get_file_name(res)
        if file_name then
            file_path = ngx.var.store_path..file_name
            file = io.open(file_path, "w+")
            if not file then
                ngx.say("failed to open file ", file_path)
                return
            end
        end

    elseif typ == "body" then
        if file then
            file:write(res)
        end

    elseif typ == "part_end" then
        if file then
            file:close()
            file = nil
            ngx.say("upload to "..file_path.." successfully!")
        end
    elseif typ == "eof" then
        break

    else
        -- do nothing
    end
end


Используется:
openresty/lua-resty-upload
lua-nginx-module

Или простейший пример на PHP:
upload.php
<!DOCTYPE html>
<html>
<head>
  <title>Upload your files</title>
</head>
<body>
  <form enctype="multipart/form-data" action="upload.php" method="POST">
    <p>Upload your file</p>
    <input type="file" name="uploaded_file"></input><br />
    <input type="submit" value="Upload"></input>
  </form>
</body>
</html>
<?PHP
  if(!empty($_FILES['uploaded_file']))
  {
    $path = "uploads/";
    $path = $path . basename( $_FILES['uploaded_file']['name']);
    if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $path)) {
      echo "The file ".  basename( $_FILES['uploaded_file']['name']). 
      " has been uploaded";
    } else{
        echo "There was an error uploading the file, please try again!";
    }
  }
?>
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
NeiroNx
@NeiroNx
Программист
Да в любом случае понадобится Backend и не важно на каком языке он будет, важно сколько файлов и какого размера надо принимать - придется настраивать ограничение размера, в PHP это 50 мегабайт по умолчанию, в питоне другое значение. Возможно питоновский скрипт придется подключать через wsgi прослойку к апачу или нгинксу.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы