%%%------------------------------------------------------------------- %%% @author anlicheng %%% @copyright (C) 2025, %%% @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.