Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Filestream Segmente über WebService machen Exe kaputt andere (https://www.delphipraxis.net/73389-filestream-segmente-ueber-webservice-machen-exe-kaputt-andere.html)

webservice 17. Jul 2006 14:17


Filestream Segmente über WebService machen Exe kaputt andere
 
Hallo zusammen,

ich will Dateien über einen WebService austauschen. Auf WebserviceSeite gibt es zum Speichern und Laden der Dateien die Methoden
  • function DoSaveToFile (Datei : Thfs_Datei) : String;
  • function DoLoadFromFile (var Datei : Thfs_Datei) : String;

Deren Code so aussieht:
Delphi-Quellcode:
function DoSaveToFile  (Datei : Thfs_Datei) : String;
var
  todatei: TFilestream;
  filename : String;
begin
  todatei := nil;

  filename := HelenFSuri (Datei.Dir + Datei.Name);
  if filename = '' then
     result := '404 Directory not found'
  else
  try
     if Datei.SegmentNr = 0 then
        If FileExists (filename) and not Datei.Replace then
           result := '301 File exists'
        else
           todatei := TFileStream.Create (filename, fmCreate or fmOpenWrite)
     else
        todatei := TFileStream.Create (filename, fmOpenWrite);

     if todatei <> nil then begin
        if Datei.SegmentNr > 1 then                                                      {Böser Fehler!!!}
           todatei.Seek (Datei.SegmentNr * Datei.SegmentSize, soBeginning);              

        todatei.Write (Datei.data[0], Length (Datei.data));

        todatei.Free;

        result := filename + ' - ' + IntToStr (Datei.SegmentNr) + '/' + IntToStr(Datei.SegmentMax);
     end;
  except
     on e : Exception do
        result := e.Message;
  end;
end;

function DoLoadFromFile (var Datei : Thfs_Datei) : String;
  var FDatei : TFilestream;
      data : TDateiDaten;

      filename : String;
      len : Integer;
begin
  result := '';

  filename := HelenFSuri (Datei.Dir + Datei.name);
  if filename <> '' then begin
     FDatei := TFileStream.Create (FileName, fmOpenRead);

     if Datei.SegmentNr = 0 then
        Datei.SegmentMax := FDatei.Size Div Datei.SegmentSize + 1;

     if FDatei.Size > ((Datei.Segmentnr) * Datei.SegmentSize) then begin
        if Datei.SegmentNr > 0 then
           FDatei.Seek ((Datei.Segmentnr) * Datei.SegmentSize, soBeginning);

        if (FDatei.Size - FDatei.Position) < Datei.SegmentSize then
           if (FDatei.Size - FDatei.Position) > 0 then
              len := FDatei.Size - FDatei.Position
           else
              len := 0
        else
           len := Datei.SegmentSize;

        SetLength (data, len);

        if len > 0 then
           FDatei.ReadBuffer (data[0], len);
        Datei.data := data;

        Datei.SegmentNr := Datei.SegmentNr + 1;
     end
     else begin
        SetLength (data, 0);
        Datei.data := data;
     end;
     
     result := filename + ' - ' + IntToStr (Datei.SegmentNr) + '/' + IntToStr(Datei.SegmentMax);
  end;
end;
Die Client Seite verwendet diese Methoden wie folgt:
Delphi-Quellcode:
//Download
procedure TForm1.Button2Click(Sender: TObject);
  var Datei : Thfs_Datei;
      PhysFile : TFileStream;
begin
  If SaveDialog1.Execute then begin
     Datei := Thfs_Datei.Create;

        Datei.SegmentNr := 0;
        Datei.Name := ExtractFilename (Edit1.Text);
        Datei.Dir := Extractfilepath (Edit1.Text);
        Datei.SegmentSize := 1024;

        PhysFile := TFileStream.Create (SaveDialog1.Filename, fmCreate);

        repeat
           Memo1.Lines.Add (GetIHFS_web_cgi.DoLoadFile(Datei));
           Application.ProcessMessages;
           Sleep(100);

           PhysFile.Write(Datei.Data[0], Length(Datei.Data));

        until Datei.SegmentNr >= Datei.SegmentMax;

        PhysFile.Free;

     Datei.Free;
  end;
end;

//Upload
procedure TForm1.Button1Click(Sender: TObject);
  var Datei : Thfs_Datei;

      PhysFile : TFileStream;
      data : TDateiDaten;
      len : Integer;

      error : String;
begin
  if Opendialog1.Execute then begin
     Datei := Thfs_Datei.Create;

     PhysFile := TFileStream.Create(Opendialog1.FileName, fmOpenRead);

     Datei.Name := ExtractFileName (OpenDialog1.FileName);
     Datei.Dir := '/';
     Datei.SegmentNr := 0;
     Datei.SegmentSize := 2048;
     Datei.SegmentMax := PhysFile.Size div Datei.SegmentSize + 1;
     Datei.Replace := false;

     error := '';

     while (Datei.SegmentNr <= Datei.SegmentMax) do begin

           if (PhysFile.Size - PhysFile.Position) < Datei.SegmentSize then
              if (PhysFile.Size - PhysFile.Position) > 0 then
                 len := PhysFile.Size - PhysFile.Position
              else
                 len := 0
           else
              len := Datei.SegmentSize;

           SetLength (data, len);
           if Len > 0 then
              PhysFile.Read(data[0], len);

           Datei.data := data;

           error := GetIHFS_web_cgi.DoSaveFile (Datei);
           if (Datei.SegmentNr = 1) and (Pos('301', error) > -1) then
              If MessageDlg ('Datei überschreiben?', mtWarning, [mbyes, mbno], 0) = mrYes then begin
                 Datei.Replace := true;
                 error := GetIHFS_web_cgi.DoSaveFile (Datei);
              end
              else
                 exit;

           Datei.SegmentNr := Datei.SegmentNr + 1;

           Memo1.Lines.Add (error);
     end;

     PhysFile.Free;

     Datei.Free;
  end;
end;
Das Object Thfs_Datei und der TDatei Array sehen so aus:
Delphi-Quellcode:
TDateiDaten = array of byte;

  Thfs_Datei = class(TRemotable)
  private
    FDir: string;
    FName: string;
    FReplace: Boolean;
    FSegmentSize: Integer;
    _checksum: string;
    _data: TDateiDaten;
    _SegmentMax: Integer;
    _SegmentNr: Integer;
  published
    property checksum: string read _checksum write _checksum;
    property data: TDateiDaten read _data write _data;
    property Dir: string read FDir write FDir;
    property Name: string read FName write FName;
    property Replace: Boolean read FReplace write FReplace;
    property SegmentMax: Integer read _SegmentMax write _SegmentMax;
    property SegmentNr: Integer read _SegmentNr write _SegmentNr;
    property SegmentSize: Integer read FSegmentSize write FSegmentSize;
  end;
Wenn ich Dateien (alles ohne .exe) übertrage funktioniert das Prinzip ohne Probleme, egal wie groß die Datei ist.
Will ich allerdings Anwendungen (alles mit .exe) übertragen, stimmen zwar am Ende die Dateigrößen, aber es sind keine ausführbaren Anwendungen mehr.

Wieso nicht?

DGL-luke 17. Jul 2006 14:19

Re: Filestream Segmente über WebService machen Exe kaputt an
 
übeträgst du ascii oder binary? beim ftp macht das anscheinend was aus, ka ob das bei deiner anwendung auch so ist.

webservice 17. Jul 2006 14:54

Re: Filestream Segmente über WebService machen Exe kaputt an
 
Hallo,

da ich die Daten mit einem FileStream auslese und in einem Array of byte zwischenlagere, gehe ich davon aus, das die Übertragung binär abläuft. Vorallem, da SOAP die Objecte korrekt umwandeln müsste.

DGL-luke 17. Jul 2006 14:55

Re: Filestream Segmente über WebService machen Exe kaputt an
 
ok... war ja nur ne vage vermutung ;)

webservice 18. Jul 2006 08:15

Re: Filestream Segmente über WebService machen Exe kaputt an
 
Diese bösen kleinen Fehlerteufelchen :twisted:

Wenn wir den Quelltext genau betrachten, fällt auf, das die Datei-Segment-Nummer bei 0 beginnt.

In der Methode DoSaveToFile steht:
Delphi-Quellcode:
if Datei.SegmentNr > 1 then
   todatei.Seek (Datei.SegmentNr * Datei.SegmentSize, soBeginning);
Folglich wird das 0. Segment an den Anfang geschrieben, das erste Segment an den Anfang geschrieben, das zweite Segment dahinter geschrieben, das dritte Segment dahinter geschrieben ... *Wir könnten dies noch bis ins unendliche fortführen*

Wenn ich das 0. Segment mit dem Ersten überschreibe, kann doch keine vernünftige Datei herauskommen.
Ich frage mich nur, warum das bei ZIP Archiven, Bildern, etc nicht aufgefallen ist...

Vielen Dank, DGL-luke für das Treten in die richtige Richtung :smile:


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz