一段关于网络传输文件的代码,请各位帮助分析分析。。给高分!!!(200分)

  • 主题发起人 主题发起人 sforever
  • 开始时间 开始时间
S

sforever

Unregistered / Unconfirmed
GUEST, unregistred user!
各位高手,我下面这段代码呢,据说是高手唐晓锋的代码,是关于网络文件传输的。
请各位能不能帮助我加上文件的传输进度啊。。。在服务器端加上文件的传输进度显示。。。

我水平太菜,实验了很多方法。都不能成功。。还有一点。能不能修改成弹出保存文件的对话框来保存文件。。这个上面默认是保存在C盘根目录下的,谁能给修改一点。。多谢了。

客户端(发送文件的)

unit mail;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls, ComCtrls;

type
TCon = record
FileName : String;
TotalSize : Integer;
Status : Integer;
end;

PCON = ^TCON;

TForm1 = class(TForm)
ClientSocket1: TClientSocket;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
Edit2: TEdit;
Button1: TButton;
Button2: TButton;
Edit3: TEdit;
OpenDialog1: TOpenDialog;
StatusBar1: TStatusBar;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
var Count : Integer;

function GetFileSize(const FileName: string):integer;
var f : TFileStream;
begin
f := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
Result :=f.Size;
F.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if clientsocket1.Socket.Connected=false then
begin
ClientSocket1.Address:=edit1.Text;
ClientSocket1.Port :=strtoint(edit2.Text);
ClientSocket1.Open;
end;
with OpenDialog1 do
begin
Execute;
if FileName <> '' then
begin
Edit3.Text :='UPLOAD '+ ExtractFileName(FileName) +' '+Inttostr(GetFileSize(FileName));
Label3.Caption := FileName;
ClientSocket1.Socket.SendText(edit3.Text);
end;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var stream : TFileStream;
Buf : pointer;
begin
stream := TFileStream.Create(label3.Caption ,fmOpenRead or fmShareDenyNone);
GetMem(Buf,stream.Size);//建立一指定大小的动态变量,并将指针指向该处
stream.Seek(0,soFromBeginning);//移动流中指针的位置,移动后指针距离数据开始的位置
stream.ReadBuffer(Buf^,stream.Size);//从流中当前位置读取流的大小
ClientSocket1.Socket.SendBuf(Buf^,stream.Size);//发送流的大小
end;

procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
StatusBar1.Align:=alBottom;
StatusBar1.SimplePanel := True;
end;

end.


服务器端(接收文件的)
unit mail;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, ComCtrls;

type
TCon = record
FileName : String;
TotalSize : Integer;
Status : Integer;
end;

PCON = ^TCON;
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
procedure FormCreate(Sender: TObject);
procedure ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
var Count : Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
Count := 0;
if serversocket1.Active=false then
begin
serversocket1.Port := 7890; //端口
ServerSocket1.Open; //Socket开始侦听
end;
end;

procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ErrorCode := 0;
end;

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var c : pcon;
begin
c :=new(pcon);
c.FileName := '';
c.TotalSize := 0 ;
c.Status := 0;
Socket.Data := c;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var C : PCON;
cmd:String;
Buffer : pointer;
n : integer;
fs : TFileStream;
const bufferSize = 1024 ;

begin
C:= Socket.Data ;
case c.Status of
0 :
begin
cmd := trim(Socket.ReceiveText) ;
if Pos('UPLOAD ',uppercase(cmd)) > 0 then
begin
c.FileName := trim(Copy(cmd,Pos(' ',cmd)+1,Length(cmd)));
c.TotalSize := StrToInt(Copy(c.FileName,Pos(' ',c.FileName)+1,Length(c.FileName)));
c.FileName := trim(Copy(c.FileName,1,Pos(' ',c.FileName)));
c.Status := 1;
Socket.Data := C;
end;
end;
1 :
begin
Count := count + 1; //发送的次数
GetMem(Buffer,BufferSize); //建立一指定大小的动态变量,并将指针指向该处
n := Socket.ReceiveBuf(Buffer^,BufferSize);//每次发送字节的大小 //接收数据包并读入缓冲区内
if not FIleExists('c:/'+c.FileName) then
begin
fs :=TFileStream.Create('c:/'+c.FileName,fmCreate or fmShareDenyNone);
fs.Seek(0,soFromBeginning);
end
else
begin
fs :=TFileStream.Create('c:/'+c.FileName,fmOpenWrite or fmShareDenyNone);
fs.Seek(0,soFromEnd);
end;
fs.WriteBuffer(Buffer^,n);
fs.Destroy;
FreeMem(Buffer);
end;
end;
end;

end.
 
这个发送代码呵呵,基本上根本不能用,测试是绝对通不过的
 
呵呵。。你老不早点告诉我。。。


我测试在本机上通过。。。。难道在网络上行不通??
 
你发个1M以上的文件看看?能用我真是服了YOU!
 
你用ClientSocket.Socket.SendStream,效果要好一些,但是还是有问题,呵呵
 
不要敝帚自珍吗,,贴出来代码来。。说出点原理来,让大家LOOK一下
 
“你用ClientSocket.Socket.SendStream,效果要好一些,但是还是有问题,呵呵”


难道不能让我一步到位吗??你还要折磨我??让我拿不成功的代码测试??
 
张无忌可是这方面的专家啊,他说的肯定是对的了
 
张无忌小心眼。我在QQ上得罪了他,他不肯告诉我。。。。

这可如何是好!!
 
我说了我回复的帖子里有详细的说明的,而且还有如何提高效率的,好好找找
这个时代,我都想当杨百劳呀![:(]
 
你的帖子有好几千。。我一个一个的找。。。。。。。找到什么时候啊。。

再说了,我看过一些你的帖子,也找过。里面说的很笼统。。。。。就三、五句代码。。感觉让人更摸不到头脑。。
你能不能共享一下你的代码啊。。。
 
给你贴一段代码,昨天没事,然后把别人的成果自己改了改,服务器端和客户端都在里面。
unit UnitClient;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ScktComp;
const
iBYTEPERSEND = 1024;
iRecvLength = 1024;
MP_FILEPROPERTY = '0'; //
MP_QUERY = '1';
MP_REFUSE = '2';
MP_ACCEPT = '3';
MP_NEXTWILLBEDATA = '4';
MP_DATA = '5';
MP_ABORT = '6';
MP_OVER = '7';
MP_CHAT = '8';
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
cs: TClientSocket;
btnConnect: TButton;
btnSendFile: TButton;
edtIPAddress: TEdit;
SaveDialog1: TSaveDialog;
SS: TServerSocket;
Label1: TLabel;
procedure btnConnectClick(Sender: TObject);
procedure btnSendFileClick(Sender: TObject);
procedure csRead(Sender: TObject; Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
procedure SSClientRead(Sender: TObject; Socket: TCustomWinSocket);
private
fsSend: TFileStream;

bReadText: boolean;
fsRecv: TFileStream;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.btnConnectClick(Sender: TObject);
begin
cs.Address := edtIPAddress.Text;
cs.Port := 2000;
cs.Active := true;
//cs.Connect;
//cs.Socket.Connect ;
end;

procedure TForm1.btnSendFileClick(Sender: TObject);
begin
if cs.Active then
if OpenDialog1.Execute then
cs.Socket.SendText(MP_QUERY + OpenDialog1.FileName); //FileSize???
end;

procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);
var
sRecv: string;
// sTemp: string;
bufSend: pointer;
iBufLength: Longint;
begin
sRecv := Socket.ReceiveText;
case sRecv[1] of
MP_REFUSE: ShowMessage('呵呵,你被拒绝了哦!');
MP_ACCEPT:
begin
fsSend := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
//iBYTEPERSEND是个常量,每次发送包的大小。
Socket.SendText(MP_FILEPROPERTY + inttostr(Trunc(fsSend.Size /
iBYTEPERSEND) + 1));
end;
MP_NEXTWILLBEDATA:
begin
if fssend.Position = fssend.Size then
begin
fsSend.Free;
fsSend := nil;
Socket.SendText(MP_OVER);
showmessage('发送完成!');
end
else
Socket.SendText(MP_NEXTWILLBEDATA);
end;
MP_DATA:
begin
GetMem(bufSend, iBYTEPERSEND + 1); //
try

//strcopy(bufSend,pchar('123'));
//fsSend.Position:=fssend.Size-1 ;
//Socket.SendBuf(bufSend^,3);
if (fsSend.Position + iBYTEPERSEND + 1) < fsSend.Size then
begin
fsSend.Read(bufSend^, iBYTEPERSEND);
Socket.SendBuf(bufSend^, iBYTEPERSEND);

//fsSend.Free; //?
end //普通的发送,大小为iBYTEPERSEND
else
begin
iBufLength := fsSend.Size - fsSend.Position;
fsSend.Read(bufSend^, iBufLength);
//fsSend.Size - fsSend.Position);
// showmessage(inttostr(fsSend.Position));
Socket.SendBuf(bufSend^, iBufLength);

end; //最后一次发送,发送剩余的数据 }
finally
FreeMem(bufSend, iBYTEPERSEND + 1); //
end; {of try}
end;
MP_ABORT:
begin
//被取消了:(
fsSend.Free;
fsSend := nil;
end;
end; {of case}

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
if ss.Active then
ss.Close;
ss.Port := 2000;
ss.Open;
bReadText := true;
end;

procedure TForm1.SSClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
sTemp: string;
bufRecv: Pointer;
iRecvLength: integer;
begin
//Socket.
if bReadText then
begin
sTemp := Socket.ReceiveText;
case sTemp[1] of
MP_QUERY:
begin
//在这里拒绝
SaveDialog1.FileName := Copy(sTemp, 2, Length(STemp));
if SaveDialog1.Execute then
begin
fsRecv := TFileStream.Create(SaveDialog1.FileName, fmCreate);
Socket.SendText(MP_ACCEPT);
end
else
Socket.SendText(MP_REFUSE + 'wrong');
end;
MP_FILEPROPERTY:
begin
//要发送StrToInt(Copy(sTemp,2,Length(sTemp))) 次
//时间进度显示。。。
Socket.SendText(MP_NEXTWILLBEDATA);
end;
MP_NEXTWILLBEDATA:
begin
bReadText := false;
Socket.SendText(MP_DATA);

end;
MP_OVER:
begin
fsRecv.Free;
//fsRecv.
bReadText := true;
showmessage('成功接收!');
end;
MP_ABORT:
begin
fsRecv.Free;
bReadText := true;
end;
MP_CHAT:
begin
//Chat Msg
end;
end; {of case}
end
else
begin
GetMem(bufRecv, 2000); //2000 must >iBYTESEND
try

iRecvLength := Socket.ReceiveLength;
Socket.ReceiveBuf(bufRecv^, iRecvLength);
fsRecv.WriteBuffer(bufRecv^, iRecvLength);
finally
FreeMem(bufRecv, 2000);
end; {of try}
bReadText := true;
Socket.SendText(MP_NEXTWILLBEDATA);
end;
end;

end.
 
呵呵,用INDY的控件吧,很好用,不用写多少行代码就可以搞掂了!
而且没有文件大小的限制(通过分包发送数据),一个字:爽!
 
上面的代码效率太低,而且用猫什么的绝对是要出问题的,
 
这个代码使用的缓存。c.totolsize就是进度的最大值,进度从0开始,每case 1 是
进度加1024,如果进度>max,是最后一个分割文件包,postion:=max,文件接收完毕。
 
其实根本没有必要要分割文件,
 
张无忌有没有必要分割文件,我不和你争执。但是我只是回答答案,问题解决了就说明可以了。
 
RE:Dephic

你知道不知道,我看着你这号人就非常的来气。。。。。动不动就说用某某控件吧。也不说说如何实现的,让我这等菜鸟看了摸不着头脑。拜托你能不能详细一点的讲给我听听。。比如象人家mypeoplelxt一样发一点代码也好啊。。


RE:mypeoplelxt

你的代码我看过了,以前也修改过。不过感觉不太好用。。。。你说的情况我没有测试过,因为没有条件测试,只是在本机上测过。发现收到的文件不能打开(EXE文件)。不知道还有没有更好的。。。。。需要说的是谢谢你的代码!!

感谢所有关注这个问题的朋友!!同样感谢Dephic
 
后退
顶部