Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > как получить имя принимаемого файла?


Автор: Dobermann 21.7.2009, 00:25
Принимаю файл через filestreem, и сохраняю его так:
Код

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
 s, sl: string;
begin
 s:= Socket.ReceiveText;
 if Reciving then
  begin
   fs.Write(s[1], length(s));
   if fs.Size=DataSize then
    begin
     fs.Free;
     Reciving:=false;
     Application.MessageBox('Файл принят');
    end;
   exit;
  end;

 if copy(s, 1, 5)='Size:' then
  begin
   sl:=copy(s, 6, Pos(#0, s)-6);
   DataSize:=StrToInt(sl);
   Delete(s, 1, Pos(#0, s));
   Reciving:=true;
   fs:=TFileStream.Create('output.dat',fmCreate);   <====
   fs.Write(s[1], length(s));
  end;
end;


НО! Ведь принимаю то я и txt, doc и rar и т.д. и каждый раз приходится менять расширение и имя у output.dat!!!

Вопрос собственно в том, как сохранять файл в потоке с его первоначальным именем и расширением??? Как это fs:=TFileStream.Create('output.dat',fmCreate); должно выглядеть???

Автор: dvamaster 21.7.2009, 06:30
судя по всему ты не передаешь имя файла с расширением, попробуй доработать: включи имя файла в строку передачи текста с размером
например так
Код

Size: 65536; Filename: filename.ext

Автор: Dobermann 21.7.2009, 07:36
Цитата(dvamaster @  21.7.2009,  07:30 Найти цитируемый пост)
судя по всему ты не передаешь имя файла с расширением, попробуй доработать: включи имя файла в строку передачи текста с размером
например так

Это да! Но размер файла я вычисляю функцией Size(), а вот как определить имя файла? 
Может отрезать весь путь до последнего слеша в filename (opendialog)??? 
Только как это будет примерно выглядеть?

Автор: Dobermann 21.7.2009, 10:31
Мда...спасиба парни! smile 
Код

function ExtractFileNameEx(FileName: string): string;
begin
  I := Length(FileName);
  if I <> 0 then
  begin
    while (FileName[i] <> '\') and (i > 0) do
      i := i - 1;
      S := Copy(FileName, i + 1, Length(FileName) - i);
      i := Length(S);
      ExtractFileNameEx:=S;
  end;
end;

Автор: dvamaster 21.7.2009, 10:48
сборщик заголовка для передачи

Код

function MakeHeader(ASize: Integer; AFileName: String): String;
begin
  Result := 'Size:' + IntToStr(ASize) + ';Filename:' + AFileName
end;


разборщик заголовка для приема

Код

procedure ParseHeader(AHeader: String; var ASize: Integer; var AFileName: String);
var
  sp, fp: Integer;
begin
  ASize := 0;
  AFileName := '';
  sp := Pos('Size:', AHeader);
  fp := Pos(';FileName:', AHeader);
  try
    ASize := StrToInt(Copy(AHeader, sp + 5, fp - sp - 5));
  except
    Exit
  end;
  AFileName := Copy(AHeader, fp + 10, Length(AHeader) - fp - 9);
end;

Автор: Dobermann 21.7.2009, 10:57
dvamaster, а как теперь принять размер, имя, и сам файл???
Код

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
 s, sl: string;
begin
 s:= Socket.ReceiveText;
 if Reciving then
  begin
   fs.Write(s[1], length(s));
   if fs.Size=DataSize then
    begin
     fs.Free;
     Reciving:=false;
     Application.MessageBox('Файл принят');
    end;
   exit;
  end;
 if copy(s, 1, 5)='Size:' then
  begin
   sl:=copy(s, 6, Pos(#0, s)-6);
   DataSize:=StrToInt(sl);
   Delete(s, 1, Pos(#0, s));
   Reciving:=true;
   fs:=TFileStream.Create('output.dat',fmCreate);   <====
   fs.Write(s[1], length(s));
  end;
end;

Что тут изменить нужно???

Автор: dvamaster 21.7.2009, 11:10
Напиши как выглядит протокол, сам я понимаю как-то так:
Код

Size:65535;Filename:filename.ext#0массив_данных_файла

так?

Добавлено через 39 секунд
между заголовком и файлом идет нулевой символ?

Автор: Dobermann 21.7.2009, 11:51
Цитата(dvamaster @  21.7.2009,  12:10 Найти цитируемый пост)
между заголовком и файлом идет нулевой символ? 

Да, это для отделения размера файла от данных находящихся в самом файле...размер файла передается в том же потоке, просто я его от данных нулевым символом разделил...

Добавлено через 43 секунды
Код

  private
    fs: TFileStream;
    Reciving: Boolean;
    DataSize: integer;
    { Private declarations }


Добавлено через 2 минуты и 59 секунд
вот так организован поток отправки размера, нулевого символа, а затем самого файла:
Код

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
 fs: TFileStream;
begin
 if Socket.ReceiveText = 'xxx' then
  begin
   fs:=TFileStream.Create(ExtractFileNameEx(OpenDialog1.FileName), fmOpenRead);
   try
    fs.Position:= 0;
    Socket.SendText('Size:'+IntToStr(fs.Size) + #0);
    Socket.SendStream(fs);
   finally
   end;
 end;
end;

Автор: dvamaster 21.7.2009, 12:00
раньше написал функцию разбора заголовка, ее и надо применять ParseHeader

Код

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
 s, sl, fn: string;
begin
 s:= Socket.ReceiveText;
 if Reciving then
  begin
   fs.Write(s[1], length(s));
   if fs.Size=DataSize then
    begin
     fs.Free;
     Reciving:=false;
     Application.MessageBox('Файл принят');
    end;
   exit;
  end;
 sl := copy(s, 1, Pos(#0, s) - 1);
 Delete(s, 1, Pos(#0, s));
 ParseHeader(sl, DataSize, fn);   <====
 Reciving:=true;
 fs:=TFileStream.Create(fn,fmCreate);
 fs.Write(s[1], length(s));
end;


Добавлено через 1 минуту и 8 секунд
повторюсь
Код

procedure ParseHeader(AHeader: String; var ASize: Integer; var AFileName: String);
var
  sp, fp: Integer;
begin
  ASize := 0;
  AFileName := '';
  sp := Pos('Size:', AHeader);
  fp := Pos(';FileName:', AHeader);
  try
    ASize := StrToInt(Copy(AHeader, sp + 5, fp - sp - 5));
  except
    Exit
  end;
  AFileName := Copy(AHeader, fp + 10, Length(AHeader) - fp - 9);
end;

Автор: Dobermann 21.7.2009, 12:30
Всем спасибо! Это сделал! smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)