![]() |
|
|
#1
|
|||
|
|||
|
Всем доброго времени суток.
Задача следующая: скачать файл с сервера, который передается им просто-напросто открытым текстом. Упрощенно говоря, сервер дает его так: Код:
#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
|
||||
|
||||
|
Ставишь компонент TIdHTTP;
Код:
var ms : TMemoryStream;
begin
ms := TMemoryStream.Create;
IdHTTP1.Get('<адрес файла в интернете>', ms);
ms.SaveToFile('<имя файла>'); |
|
#3
|
|||
|
|||
|
Цитата:
уЧИСЬ ЧИТАТЬ |
|
#4
|
|||
|
|||
|
раз речь идет о скачке, я немного спрошу по этому курсу?) только по поводу IdHTTP;
вот я качаю какой-либо файл... как определить его загрузку посредствои progressbar? не подскажите? ![]() |
|
#5
|
|||
|
|||
|
используя idHTTP вроде никак, лучше winInet юзать
|
|
#6
|
|||
|
|||
|
ну хорошо, 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
|
|||
|
|||
|
если знаешь скорость и размер делим размер на скорость получаем время
|
|
#8
|
|||
|
|||
|
а если незнаю?
![]() |
|
#9
|
|||
|
|||
|
раз у тебя есть прогресс бар значит знаешь
|
|
#10
|
|||
|
|||
|
нет, не знаю.. надо ведь сначала получить размер из файла, и скорость получить (это я подавно не знаю)... и в каком формате время выдасться?
|
|
#11
|
|||
|
|||
|
у тебя буфер равен 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;Это я выдрал из своего класса, много у тебя нет, но основно смысл должен быть понять. |
|
#12
|
|||
|
|||
|
должен
![]() я впервые этот компонент увидел мне просто помогли с закачкой, а уж про размер файла оповестить не сумели... |
|
#13
|
|||
|
|||
|
Цитата:
Попробуй определять размер последнего принимаемого блока. У тебя стоит размер 4196 для всех. А если размер завершающего, положим, 2000... Получим 2196 байт мусора... вот и появляется в конце файлов невесть что. Не пользовался приведёнными тобой функциями. Если функция Recv возвращает размер принятого блока(у тебя помещает длина блока в переменную iRet) то в строке BlockWrite(outy, BigRecy, 4196); замени цифру 4196 на переменную iRet. Т.е. BlockWrite(outy, BigRecy, iRet); Если нет, значит надо придумать как. Мысль я тебе дал. ![]() Последний раз редактировалось Амон, 17.11.2008 в 20:00. |
|
#14
|
|||
|
|||
|
Цитата:
советую реализовать если это возможно и достаточно знаний на php ![]() |
|
#15
|
|||
|
|||
|
Цитата:
TForm1.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer); Последний параметр - кол-во считанных байт. Инкрементный или за блок - не помню, попробуешь - определишь. Только придется в 2 этапа делать. Сначала получаешь размер ресурса, потом качаешь и вычисляешь %%. |