80 lines
2.8 KiB
Erlang
80 lines
2.8 KiB
Erlang
%%%-------------------------------------------------------------------
|
|
%%% @author anlicheng
|
|
%%% @copyright (C) 2025, <COMPANY>
|
|
%%% @doc
|
|
%%%
|
|
%%% @end
|
|
%%% Created : 12. 11月 2025 17:08
|
|
%%%-------------------------------------------------------------------
|
|
-module(upload_channel).
|
|
-author("anlicheng").
|
|
|
|
%% API
|
|
-export([init/2]).
|
|
|
|
init(Req0, Opts) ->
|
|
Method = binary_to_list(cowboy_req:method(Req0)),
|
|
lager:debug("[upload_channel] method is: ~p", [Method]),
|
|
|
|
Headers = cowboy_req:headers(Req0),
|
|
lager:debug("headers is: ~p", [Headers]),
|
|
case maps:find(<<"content-type">>, Headers) of
|
|
{ok, <<"application/octet-stream">>} ->
|
|
Filename = maps:get(<<"x-filename">>, Headers),
|
|
case filename:extension(Filename) of
|
|
<<>> ->
|
|
Req = cowboy_req:reply(400, #{
|
|
<<"Content-Type">> => <<"text/html;charset=utf-8">>
|
|
}, <<"Miss file extension">>, Req0),
|
|
{ok, Req, Opts};
|
|
_ ->
|
|
Basename = filename:basename(Filename),
|
|
handle_raw_file(Req0, binary_to_list(Basename)),
|
|
Req2 = cowboy_req:reply(400, #{
|
|
<<"Content-Type">> => <<"text/html;charset=utf-8">>
|
|
}, <<"ok">>, Req0),
|
|
{ok, Req2, Opts}
|
|
end;
|
|
{ok, ContentType} ->
|
|
lager:debug("[upload_channel] unexpect content-type: ~p", [ContentType]),
|
|
Req = cowboy_req:reply(400, #{
|
|
<<"Content-Type">> => <<"text/html;charset=utf-8">>
|
|
}, <<"Expected application/octet-stream">>, Req0),
|
|
{ok, Req, Opts};
|
|
error ->
|
|
Req = cowboy_req:reply(400, #{
|
|
<<"Content-Type">> => <<"text/html;charset=utf-8">>
|
|
}, <<"Miss content-type header">>, Req0),
|
|
{ok, Req, Opts}
|
|
end.
|
|
|
|
%% 读取请求体
|
|
handle_raw_file(Req, Basename) ->
|
|
Filename = make_file(Basename),
|
|
{ok, IoDevice} = file:open(Filename, [write]),
|
|
ok = handle_raw_file0(Req, IoDevice),
|
|
ok = file:close(IoDevice).
|
|
|
|
handle_raw_file0(Req, IoDevice) ->
|
|
case cowboy_req:read_body(Req) of
|
|
{ok, Data, Req1} ->
|
|
file:write(IoDevice, Data),
|
|
ok;
|
|
{more, Data, Req1} ->
|
|
file:write(IoDevice, Data),
|
|
handle_raw_file0(Req1, IoDevice)
|
|
end.
|
|
|
|
make_file(Basename) when is_list(Basename) ->
|
|
{ok, UploadDir} = application:get_env(efka, upload_dir),
|
|
{{Y, M, D}, _} = calendar:local_time(),
|
|
DateDir = io_lib:format("~p-~p-~p", [Y, M, D]),
|
|
BaseDir = UploadDir ++ DateDir,
|
|
case filelib:is_dir(BaseDir) of
|
|
true ->
|
|
ok;
|
|
false ->
|
|
ok = file:make_dir(BaseDir)
|
|
end,
|
|
BaseDir ++ "/" ++ Basename.
|