Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 14.11.2008, 19:46
NetWorker NetWorker вне форума
Прохожий
 
Регистрация: 14.11.2008
Сообщения: 1
Репутация: 10
По умолчанию Скачивание файла

Всем доброго времени суток.
Задача следующая: скачать файл с сервера, который передается им просто-напросто открытым текстом. Упрощенно говоря, сервер дает его так:
Код:
#perl here
#$client - дескриптор клиента, IO::Socket
open (IN, "<transfer.dat") or die;
foreach (<IN>) { print $client $_; }
close IN;
close $client;

Но это лирика, сервер гарантированно работает, проверялось клиентом на перле.

Клиент должен этот файл корректно принять и записать на диск. Но есть одно но: нельзя использовать никаких компонентов, ни инди, ни прочих качалок, исключительно WinSock.

Сам я, в течении уже третьего вечера пытаюсь реализовать сие дело таким образом:
Код:
//delphi here
Procedure net;
var
  Outy      : File of char;
  BigRecy  : array[0..4196] of char;
  iRet       : integer;
begin
// здесь идет реализация сокетов и прочая романтика,
// к делу относящаяся лишь посредственно
      AssignFile (Outy, GetCurrentDir() + '\' + 'test.bin');
      ReWrite(Outy);

      while (iRet<>0) do
      begin
        iRet := Recv(sServerListen, BigRecy, length(BigRecy), 0);
        if (iRet = 0) then
          break;
          BlockWrite(outy, BigRecy, 4196);
        end;

      close (Outy);

end;

Таким образам передавались разные типы файлов, от `man iptables`, то есть простого текста, до картинок и музыки. Результаты следующие: Начало и середина текста выглядели, вроде бы, адекватно, но конец иногда дублировался, иногда образался, всегда по-разному. Вместо невинной картинки приходила какая-то невнятная цветная мазня. С мп3 дело обстоит немного лучше, трек либо укорачивался, либо удлиннялся, с пробелами(которые плеер просто пропускал) примерно по 0.2 сек.

Так как таким образом планируется передавать в основном исполняемые файлы, подобные баги-глюки-лаги абсолютно неприемлемы.

Буду благодарен за комментарии по теме, особенно за рабочий код.
Ответить с цитированием
  #2  
Старый 15.11.2008, 13:16
Аватар для mak-karpov
mak-karpov mak-karpov вне форума
Активный
 
Регистрация: 18.09.2008
Сообщения: 235
Версия Delphi: 2010 и 7
Репутация: 1242
По умолчанию

Ставишь компонент TIdHTTP;
Код:
var ms : TMemoryStream;
begin
  ms := TMemoryStream.Create;
  IdHTTP1.Get('<адрес файла в интернете>', ms);
  ms.SaveToFile('<имя файла>');
__________________
Кнопка "+" - весы в правом верхнем углу сообщения...
Ответить с цитированием
  #3  
Старый 15.11.2008, 13:56
ApxaHGe1 ApxaHGe1 вне форума
Активный
 
Регистрация: 08.04.2008
Адрес: Нижний новгород
Сообщения: 311
Репутация: 38
По умолчанию

Цитата:
Сообщение от mak-karpov
Ставишь компонент TIdHTTP;
Код:
var ms : TMemoryStream;
begin
  ms := TMemoryStream.Create;
  IdHTTP1.Get('<адрес файла в интернете>', ms);
  ms.SaveToFile('<имя файла>');
Но есть одно но: нельзя использовать никаких компонентов, ни инди, ни прочих качалок, исключительно WinSock.
уЧИСЬ ЧИТАТЬ
Ответить с цитированием
  #4  
Старый 16.11.2008, 22:24
ApplicatiOn ApplicatiOn вне форума
Активный
 
Регистрация: 28.02.2008
Сообщения: 388
Репутация: -10
По умолчанию

раз речь идет о скачке, я немного спрошу по этому курсу?) только по поводу IdHTTP;

вот я качаю какой-либо файл...

как определить его загрузку посредствои progressbar? не подскажите?
Ответить с цитированием
  #5  
Старый 16.11.2008, 22:26
Alexo Alexo вне форума
Начинающий
 
Регистрация: 24.01.2007
Сообщения: 191
Репутация: 15
По умолчанию

используя idHTTP вроде никак, лучше winInet юзать
__________________
Delphi - это лишь инструмент, а что ты сможешь создать при помощи этого инструмента, зависит исключительно от тебя.
Ответить с цитированием
  #6  
Старый 16.11.2008, 22:30
ApplicatiOn ApplicatiOn вне форума
Активный
 
Регистрация: 28.02.2008
Сообщения: 388
Репутация: -10
По умолчанию

ну хорошо, winInet.. отъюзал

Код:
function GetInetFile(const fileURL, FileName: string): boolean;
const
  BufferSize = 1024;
var
  hSession, hURL: HInternet;
  Buffer: array[1..BufferSize] of Byte;
  BufferLen: DWORD;
  f: file;
  sAppName: string;
begin
  Result := False;
  sAppName := ExtractFileName(Application.ExeName);
  hSession := InternetOpen(PChar(sAppName),
  INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  try
    hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0);
    try
      AssignFile(f, FileName);
      Rewrite(f,1);
      repeat
        InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
        BlockWrite(f, Buffer, BufferLen);
      until
        BufferLen = 0;
      CloseFile(f);
      Result := True;
    finally
      InternetCloseHandle(hURL);
    end;
  finally
    InternetCloseHandle(hSession);
  end;
end;


Код:
var
  FileOnNet, LocalFileName: string;
begin
  FileOnNet := Edit1.Text;
  LocalFileName := Edit2.Text;

  if GetInetFile(FileOnNet, LocalFileName) = True then
    ShowMessage('Загрузка завершена')
  else
    ShowMessage('Ошибка при закачке файла');
end;

и ставим прогрессбар на панель:

Код:
procedure TForm1.FormCreate(Sender: TObject);
begin
  with ProgressBar1 do
  begin
    Parent := StatusBar1;
    Position := 0;
    Top := 2;
    Left := 0;
    Height := StatusBar1.Height - Top;
    Width := StatusBar1.Panels[0].Width - Left;
  end;
end;

осталось только отловить оставшееся время закачки
Ответить с цитированием
  #7  
Старый 16.11.2008, 22:31
Alexo Alexo вне форума
Начинающий
 
Регистрация: 24.01.2007
Сообщения: 191
Репутация: 15
По умолчанию

если знаешь скорость и размер делим размер на скорость получаем время
__________________
Delphi - это лишь инструмент, а что ты сможешь создать при помощи этого инструмента, зависит исключительно от тебя.
Ответить с цитированием
  #8  
Старый 16.11.2008, 22:32
ApplicatiOn ApplicatiOn вне форума
Активный
 
Регистрация: 28.02.2008
Сообщения: 388
Репутация: -10
По умолчанию

а если незнаю?
Ответить с цитированием
  #9  
Старый 16.11.2008, 22:32
Alexo Alexo вне форума
Начинающий
 
Регистрация: 24.01.2007
Сообщения: 191
Репутация: 15
По умолчанию

раз у тебя есть прогресс бар значит знаешь
__________________
Delphi - это лишь инструмент, а что ты сможешь создать при помощи этого инструмента, зависит исключительно от тебя.
Ответить с цитированием
  #10  
Старый 16.11.2008, 22:34
ApplicatiOn ApplicatiOn вне форума
Активный
 
Регистрация: 28.02.2008
Сообщения: 388
Репутация: -10
По умолчанию

нет, не знаю.. надо ведь сначала получить размер из файла, и скорость получить (это я подавно не знаю)... и в каком формате время выдасться?
Ответить с цитированием
  #11  
Старый 16.11.2008, 22:43
Alexo Alexo вне форума
Начинающий
 
Регистрация: 24.01.2007
Сообщения: 191
Репутация: 15
По умолчанию

у тебя буфер равен 1024 байтов 1 КБ воемя за которое он закачет 1 кб за секунду сколько он КБ закачает такова и скорость

Вот получение размера файла

Код:
function THttpGet.getResourceSize(const AURL: String): Integer;
var
   hOpen, hConnect, hResource: HINTERNET;
   host, resource: string;
   buflen, tmp: DWORD;
begin
  hOpen := nil;
  hConnect := nil;
  hResource := nil;
  try
    ParseURL(AURL, host, resource);

    if not fError then begin
      hOpen := InternetOpen(fUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
      CheckError;
      if not fError then
        hConnect := InternetConnect(hOpen, PChar(host), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
      CheckError;
      if not fError then
        hResource := HttpOpenRequest(hConnect, 'HEAD', PChar(resource), nil, nil, nil, 0, 0);
      CheckError;
      if not fError then
        HttpSendRequest(hResource, nil, 0, nil, 0);
      CheckError;
    end;

    if not fError then begin
      buflen := SizeOf(Result);
      tmp := 0;
      Result := 0;
      HttpQueryInfo(hResource, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER,
      @Result, buflen, tmp);
      CheckError;
    end else
      Result := 0;

      InternetCloseHandle(hConnect);
      InternetCloseHandle(hOpen);
  except
    on E: Exception do
      ShowMessage(E.Message);
  end;

end;

Это я выдрал из своего класса, много у тебя нет, но основно смысл должен быть понять.
__________________
Delphi - это лишь инструмент, а что ты сможешь создать при помощи этого инструмента, зависит исключительно от тебя.
Ответить с цитированием
  #12  
Старый 16.11.2008, 22:50
ApplicatiOn ApplicatiOn вне форума
Активный
 
Регистрация: 28.02.2008
Сообщения: 388
Репутация: -10
По умолчанию

должен

я впервые этот компонент увидел мне просто помогли с закачкой, а уж про размер файла оповестить не сумели...
Ответить с цитированием
  #13  
Старый 17.11.2008, 19:47
Амон Амон вне форума
Прохожий
 
Регистрация: 09.11.2008
Сообщения: 14
Репутация: 10
По умолчанию

Цитата:
Сообщение от NetWorker
Код:
//delphi here
Procedure net;
var
  Outy      : File of char;
  BigRecy  : array[0..4196] of char;
  iRet       : integer;
begin
// здесь идет реализация сокетов и прочая романтика,
// к делу относящаяся лишь посредственно
      AssignFile (Outy, GetCurrentDir() + '\' + 'test.bin');
      ReWrite(Outy);

      while (iRet<>0) do
      begin
        iRet := Recv(sServerListen, BigRecy, length(BigRecy), 0);
        if (iRet = 0) then
          break;
          BlockWrite(outy, BigRecy, 4196);
        end;

      close (Outy);

end;

Попробуй определять размер последнего принимаемого блока. У тебя стоит размер 4196 для всех. А если размер завершающего, положим, 2000... Получим 2196 байт мусора... вот и появляется в конце файлов невесть что.

Не пользовался приведёнными тобой функциями.
Если функция Recv возвращает размер принятого блока(у тебя помещает длина блока в переменную iRet) то в строке BlockWrite(outy, BigRecy, 4196); замени цифру 4196 на переменную iRet. Т.е. BlockWrite(outy, BigRecy, iRet);
Если нет, значит надо придумать как. Мысль я тебе дал.

Последний раз редактировалось Амон, 17.11.2008 в 20:00.
Ответить с цитированием
  #14  
Старый 25.11.2008, 17:38
olegteror olegteror вне форума
Прохожий
 
Регистрация: 31.10.2007
Сообщения: 31
Репутация: 10
По умолчанию

Цитата:
#perl here
#$client - дескриптор клиента, IO::Socket
open (IN, "<transfer.dat") or die;
foreach (<IN>) { print $client $_; }
close IN;
close $client;


советую реализовать если это возможно и достаточно знаний на php
Ответить с цитированием
  #15  
Старый 25.11.2008, 17:42
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,036
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от ApplicatiOn
раз речь идет о скачке, я немного спрошу по этому курсу?) только по поводу IdHTTP;

вот я качаю какой-либо файл...

как определить его загрузку посредствои progressbar? не подскажите?

TForm1.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Integer);


Последний параметр - кол-во считанных байт. Инкрементный или за блок - не помню, попробуешь - определишь. Только придется в 2 этапа делать. Сначала получаешь размер ресурса, потом качаешь и вычисляешь %%.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 15:25.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter