Como o titulo já fala, neste artigo a minha proposta é mostrar como é simples transferir arquivos pela rede, de qualquer computador para qualquer computador. As aplicações para essa prática vão de acordo com a imaginação de cada programador. Mas como exemplos podem ser para transferir um banco de dados de uma loja matriz para as filiais, fazer um servidor de arquivos pessoais, gerenciador de rede, e outras mais.
Esse artigo vem pra complementar um outro que fiz e pode ser visto nesse link:
http://www.activedelphi.com.br/modules.php?op=modload&name=News&file=article&sid=249&mode=thread&order=0&thold=0
Primeiro, enviar.
Através dos componentes TServerSockets e TClientSockets conseguimos
ligar vários computadores em uma rede. E como foi visto no primeiro
artigo conseguimos facilmente enviar strings com o comando
ClientSocket1.Socket.SendText(‘Meu String’);
Para a transferência de arquivos iremos utilizar o comando
ClientSocket1.Socket.SendBuf(var
Buf; Count : integer);
Como podemos observer, teremos que informar dois parâmetros que nada
mais é que a velha dupla conhecido, endereço e offset, ou ponteiro
e deslocamento. Então é fácil deduzir que só temos
que enviar o endereço do arquivo e o seu tamanho em bytes. Mas a pergunta
que vem é "Como pegar esse endereço e o tamanho?"
Simples! O Delphi tem uma classe chamada TMemoryStream. Com ela teremos
tudo que precisamos. Então trate de declarar uma variável
global assim:
ArqTmp : TMemoryStream;
E criá-lo no evento onCreate do Form Assim:
procedure TForm1.FormCreate(Sender: TObject);
begin
ArqTmp := TMemoryStream.Create;
end;
Vale lembrar que estamos primeiro construindo a aplicação cliente,
que vai enviar o arquivo.
Com nosso stream construído iremos carregar o arquivo e enviar. Para
isso coloquei um button e um opendialog para facilitar a vida, ficou assim:
procedure TForm1.Button2Click(Sender: TObject);
Var
Tamanho : Int64;
begin
if OpenDialog1.Execute then
Begin
ArqTmp.Clear; // Limpo o stream
ArqTmp.LoadFromFile(OpenDialog1.FileName); // Carrego
Tamanho := ArqTmp.Size; // Gravo o tamanho
em
uma variavel
ClientSocket1.Socket.SendBuf(Tamanho,SizeOf(Int64)); // Envio o inteiro
ClientSocket1.Socket.SendBuf(ArqTmp.Memory^,ArqTmp.Size); //
vai arquivo…
end;
end;
Você deve observar que eu enviei um inteiro com o tamanho do arquivo
antes de enviar o arquivo. Porque??? – Por que lá na aplicação
servidora, quando a gente for receber o arquiv,o temos que saber qual o tamanho
do arquivo para poder parar e gravar o arquivo. Entendido?
Pronto basicamente é isso, a aplicação cliente é mais
simples.

Figura1. Aplicação Cliente
Agora é receber.
Para receber a idéia é: Primeiro vem os bytes com o tamanho
do arquivo, os bytes seguintes são o próprio arquivo. Então
vou guardando ate chegar todos os bytes do arquivo então eu gravo ele
no meu HD.
Qualquer informação que chegue no servidor ele “dispara” o
evento OnClientRead e é lá que iremos receber
nosso arquivinho :-) com a ajuda da função
Socket.ReceiveBuf(var Buf; Count : integer);
Aqui passamos também endereço e a quantidade de bytes que iremos
escrever. Para saber quantos bytes iremos escrever vamos utilizar a função:
Socket.ReceiveLength;
E o endereço vai estar no ponteiro que vamos criar. Aqui também
iremos criar um TMemoryStream e iremos gravar o que lermos através
do ReceiveBuf. O evento completo ficou assim:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
Var TamBuffer : integer;
Paux : pointer;
begin
if not RecebendoArquivo then
Begin
Socket.ReceiveBuf(TamanhoArquivo,sizeof(Int64));
RecebendoArquivo := True;
if Arquivo = nil then
Arquivo := TMemoryStream.Create;
ProgressBar1.Max := TamanhoArquivo;
end
else
Begin
TamBuffer := Socket.ReceiveLength;
GetMem(PAux,TamBuffer);
Socket.ReceiveBuf(PAux^,TamBuffer);
Arquivo.Write(PAux^,TamBuffer);
Dispose(PAux);
ProgressBar1.Position := Arquivo.Size;
if TamanhoArquivo = Arquivo.Size then
Begin
RecebendoArquivo := False;
ShowMessage ('Transferencia completa');
If SaveDialog1.Execute then
Arquivo.SaveToFile(SaveDialog1.FileName);
Arquivo.Free;
Arquivo := Nil;
ProgressBar1.Position := ProgressBar1.Min;
end;
end;
end;
Observe como é simples. Coloquei um ProgressBar para ficar mais
chique, e é legal
quando se tem arquivos grandes. E coloquei também um SaveDialog para
que se informe onde vai ser salvo o arquivo e o nome. As minhas variáveis
globais ficaram assim:
var
Form1: TForm1;
TamanhoArquivo : Int64;
Arquivo : TMemoryStream;
RecebendoArquivo : Boolean;
E no onCreate do form iniciei o RecebendoArquivo como false.

Figura2. Aplicação Servidora.
Para quem tiver dúvidas meu e-mail é
jnelson3@ig.com.br . Acreditem,
eu respondo :-)
Clique aqui para fazer o download do exemplo.
Nelson Lima
NelSoft – Agente pensa a gente faz.
|