在Delphi中,FTP可以用于一般的文件传输吗?
我正在使用TidTtilityFTP服务器n TidTtilityFTP进行p2p文件传输,它适用于文本文件传输,但当我尝试docx和pdf文件时,虽然文件已传输,但无法打开,或者pdf表示文件已损坏。如此链接所示 “FTP客户端基于普通文件传输协议。此客户端 可用于连接到TFTP服务器。TFTP不用于一般文件传输,因为它 是一种非常轻量级的文件传输协议。它通常仅限于局域网,用于 简单的任务,例如从路由器上传/下载路由表。由于 本协议的性质,在需要身份验证时不建议使用 或一般需要任何类型的担保” FTP和TFTP不是不同吗?或者上面的文本对于两者都是相同的吗 这是密码 客户:在Delphi中,FTP可以用于一般的文件传输吗?,delphi,delphi-xe3,Delphi,Delphi Xe3,我正在使用TidTtilityFTP服务器n TidTtilityFTP进行p2p文件传输,它适用于文本文件传输,但当我尝试docx和pdf文件时,虽然文件已传输,但无法打开,或者pdf表示文件已损坏。如此链接所示 “FTP客户端基于普通文件传输协议。此客户端 可用于连接到TFTP服务器。TFTP不用于一般文件传输,因为它 是一种非常轻量级的文件传输协议。它通常仅限于局域网,用于 简单的任务,例如从路由器上传/下载路由表。由于 本协议的性质,在需要身份验证时不建议使用 或一般需要任何类型的担保”
procedure TForm2.LoadClick(Sender: TObject);
begin
OpenDialog1.InitialDir := GetCurrentDir;
if OpenDialog1.Execute then
begin
Edit1.Text := OpenDialog1.FileName;
path := Edit1.Text; // save path for sending
end;
end;
procedure TForm2.sendClick(Sender: TObject);
var
size: Word;
index: Word;
buffer: TIdBytes;
begin
stream := TFileStream.Create(path,fmOpenRead or fmShareDenyWrite);
try
setlength(buffer, stream.Size);
stream.ReadBuffer(buffer, Length(buffer));
stream.Position := 0;
Client1.Put(stream, ExtractFileName(path));
finally
stream.Free;
end;
end;
procedure TForm2.client1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
begin
Memo1.Lines.Add(IntToStr(AWorkCount));
end;
procedure TForm2.client1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
AWorkCountMax: Int64);
begin
Memo1.Lines.Add('Transmitting data...');
end;
procedure TForm2.client1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
Memo1.Lines.Add('Transfer complete...');
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
server.Create;
server.ThreadedEvent := True;
server.Active := True;
server.Bindings.Add.Port := 69;
Client1.Host := '';
Client1.Port := 69;
end;
服务器:
procedure TForm2.serverWriteFile(Sender: TObject; var FileName: string;
const PeerInfo: TPeerInfo; var GrantAccess: Boolean; var AStream: TStream;
var FreeStreamOnComplete: Boolean);
var
FS: TFileStream;
begin
SaveDialog1.FileName := ExtractFileName(FileName);
if SaveDialog1.Execute then
begin
// let TIdTrivialFTPServer create the TFileStream internally...
FileName := SaveDialog1.FileName;
Memo1.Lines.Add('started writing files...');
// file1 := ExtractFileName(Filename);
{ Open file in WRITE ONLY mode }
FS := TFileStream.Create(TFTPPath + Filename,fmCreate or fmShareExclusive);
{ Copy all the data }
AStream := FS;
{ Set parameters }
FreeStreamOnComplete := True;
end
else
GrantAccess := False;
end;
普通FTP(TFTP)是一种基于UDP的轻量级文件传输协议。如描述所述,它通常仅用于简单传输,如与基于局域网的路由器交互。对于更健壮的传输,您应该使用基于TCP/IP的文件传输,例如使用TIdFTP
和TIdFTPServer
,甚至使用HTTP传输,例如使用TIdHTTP
和tidhtpserver
尽管如此,以下客户端线路是错误的:
stream.ReadBuffer(buffer, Length(buffer));
您没有正确地将流
内容读入缓冲区
,因此正在损坏堆栈上的内存。您使用的是动态数组,因此必须对数组进行索引,以便将数组分配的内存地址传递给ReadBuffer()
,例如:
stream.ReadBuffer(buffer[0], Length(buffer));
或者:
stream.ReadBuffer(Pointer(buffer)^, Length(buffer));
首先,为什么要将文件数据读入本地TIdBytes
?除浪费内存外,您不会将其用于任何其他用途,因此请将其丢弃:
procedure TForm2.sendClick(Sender: TObject);
var
stream: TFileStream;
begin
stream := TFileStream.Create(path, fmOpenRead or fmShareDenyWrite);
try
Client1.Put(stream, ExtractFileName(path));
finally
stream.Free;
end;
end;
在服务器端,工作线程中会触发OnWriteFile
(和OnReadFile
)事件,因此直接访问TSaveDialog
和TMemo
组件是不安全的。您必须与主线程同步才能安全访问它们,例如:
procedure TForm2.serverWriteFile(Sender: TObject; var FileName: string;
const PeerInfo: TPeerInfo; var GrantAccess: Boolean; var AStream: TStream;
var FreeStreamOnComplete: Boolean);
begin
GrantAccess := False;
TThread.Synchronize(nil,
procedure
begin
SaveDialog1.FileName := ExtractFileName(FileName);
GrantAccess := SaveDialog1.Execute;
if GrantAccess then FileName := SaveDialog1.FileName;
end
);
if GrantAccess then
begin
{ Open file in WRITE ONLY mode }
AStream := TFileStream.Create(Filename, fmCreate or fmShareExclusive);
FreeStreamOnComplete := True;
TThread.Synchronize(nil,
procedure
begin
Memo1.Lines.Add('started writing a file...');
end
end;
end;
end;
请出示你的密码。
TransferMode
属性可以设置为tfNetAscii
,这对于ASCII文本文件很好,而tfOctet
则用于二进制数据。提示:FTP具有类似的设置/模式。我需要一个通用的文件传输协议。代码添加在上面。@Marcus将其设置为tfoctet。@MarcusAdams:TransferMode
实际上不是由TidLittleFTP
或TidLittleFTPServer
实现的。虽然tidtilityftp
将TransferMode
发送到TFTP服务器,并且tidtilityftpserver
确实提取接收到的TransferMode
,但两个组件实际上都没有使用指定的模式。它们都仅在tfOctet
模式下执行传输。