Search code examples
filesocketserlanggen-tcp

Erlang: send file and filename


I'm interesting to send a file and it's filename. Server's options:

-define(TCP_OPTIONS_SERVER, [binary, {packet, 0}, {active, false}]).

That's the receiver loop:

file_receiver_loop(Socket,Bs)->
case gen_tcp:recv(Socket, 0) of
    {ok, B} ->
        file_receiver_loop(Socket, [Bs, B]);
    {error, closed} ->
        io:format("~nReceived!~n ~p",[Bs]),
        save_file(Bs)
end.

I send file with:

file:sendfile(FilePath, Socket),

When I send file and filename

gen_tcp:send(Socket,Filename),
file:sendfile(FilePath, Socket),

The Binary Data has a variable structure.

Thanks all!


Solution

  • I make this code to solve the problem.
    I send 30 byte for the file name.
    If the filename<30 I use the padding with white char.
    When the connection is accepted I call function file_name_receiver(Socket), that receive the filename:

    file_name_receiver(Socket)->
        {ok,FilenameBinaryPadding}=gen_tcp:recv(Socket,30),
        FilenamePadding=erlang:binary_to_list(FilenameBinaryPadding),
        Filename = string:strip(FilenamePadding,both,$ ),
        file_receiver_loop(Socket,Filename,[]).
    

    This function riceive the binary data file:

    file_receiver_loop(Socket,Filename,Bs)->
        io:format("~nRicezione file in corso~n"),
        case gen_tcp:recv(Socket, 0) of
        {ok, B} ->
            file_receiver_loop(Socket, Filename,[Bs, B]);
        {error, closed} ->
            save_file(Filename,Bs)
    end.
    

    Finally, this function save the file.

    %%salva il file
    save_file(Filename,Bs) ->
        io:format("~nFilename: ~p",[Filename]),
        {ok, Fd} = file:open("../script/"++Filename, write),
        file:write(Fd, Bs),
        file:close(Fd).
    

    The sender use a simple function:

    %%Permette l'invio di un file specificando host,filename e path assoluto
    send_file(Host,Filename,FilePath,Port)->
        {ok, Socket} = gen_tcp:connect(list_to_atom(Hostname), Port,          TCP_OPTIONS_CLIENT),
        FilenamePadding = string:left(Filename, 30, $ ), %%Padding with white space
        gen_tcp:send(Socket,FilenamePadding),
        Ret=file:sendfile(FilePath, Socket),
        ok = gen_tcp:close(Socket).