Pregunta

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!

¿Fue útil?

Solución

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).

Otros consejos

I have made two function where you can send binary files with message passing.

%Zip a file or a folder
send_zip(Pid, FolderName) ->
    %Name of you zip file
    FolderNameZip= FolderName++".zip",   
    %Zip the folder/file from the computer and name the zip file by FornderNameZip                    
    {ok, ZipFile} = zip:create(FolderNameZip, [FolderName]),
    %Put the Zipfile in a variable 
    {ok, ZipHandle} = file:read_file(ZipFile),
    %Send the zipfile to the other PID, sends the zipfile and his name to name it the same way.
    Pid ! {finish, ZipHandle, FolderNameZip}.


%save and unzip the in the computer 
register_zip_bash(Dir, ZipHandle, FolderNameZip) -> 
    file:write_file(FolderNameZip, ZipHandle),
    Cmd2 = io_lib:format("unzip -o -j ~p -d ~p/",[FolderNameZip, Dir]),
    _=os:cmd(Cmd2).

FoldeName can be the name of your file or your folder in your computer. Pid is the persone who you would like to send the message.

When you receive the ZipHandle, and the FolderNameZip use the register_zip_bash(...) function to save the data in your computer. Dir is the directory of where you would like to save the data. ZipHandle is the binary file that you receive from the PID function. FolderNameZip is the name of where the ZipHandle will be saved in the computer.

As you can see, send_zip(...) uses a erlang function and register_zip_bash(...) uses a bash command. You DO NOT HAVE to zip file to send the data. Don't hesitate to change the code to make it suitable for you.

Hope this will help, Cheers.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top