2013-12-16 23 views
-1

我使用tidtrivialftp服務器n tidtrivialftp爲p2p文件傳輸,它適用於文本文件傳輸,但是當我嘗試docx和pdf文件,雖然文件傳輸但它無法打開或PDF說它的損壞。如此鏈接說http://www.swissdelphicenter.ch/article_data/ch20.pdfDelphi Tidtrivialftp可以用於一般的文件傳輸嗎?

」TIdTrivialFTP客戶端基於普通文件傳輸協議,該客戶端 可用於連接TFTP服務器。TFTP不適用於一般文件傳輸,因爲它是一個非常輕量級的文件傳輸協議。侷限於局域網並用於 等簡單任務,例如從路由器上傳/下載路由表。由於此協議的性質爲 ,因此在請求認證時不推薦使用通常需要使用 或任何類型的安全「。

是不是TIdTrivialFTP和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; 
+0

請顯示您的代碼。 'TransferMode' propery可以設置爲'tfNetAscii',這對於ASCII文本文件很好,'tfOctet',對於二進制數據。提示:FTP具有類似的設置/模式。 –

+0

我需要一個通用的文件傳輸協議。代碼在上面添加。 –

+0

@Marcus它設置爲tfoctet。 –

回答

1

普通FTP(TFTP)是基於UDP的輕量級文件傳輸協議。就像描述所說的那樣,它通常只用於簡單傳輸,比如與基於局域網的路由器進行交互。爲了實現更強大的傳輸,您應該使用基於TCP/IP的文件傳輸,例如使用TIdFTPTIdFTPServer,或者甚至使用HTTP傳輸,例如TIdHTTPTIdHTTPServer

雖這麼說,下面的客戶端線是錯誤的:

stream.ReadBuffer(buffer, Length(buffer)); 

你是不是讀stream內容到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)事件被觸發的工作線程,因此直接訪問您的TSaveDialogTMemo組件並不安全。您必須與主線程同步才能安全訪問它們,例如:

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; 
相關問題