![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Помогите сделать докачку при скачивании с idhttpserver.
у меня программа-сервак (idhttpserver) раздаёт файлы, и в случае обрыва скачивание начинается сначала. сервер версии инди10 Последний раз редактировалось Snake22, 30.11.2012 в 18:53. |
|
#2
|
||||
|
||||
|
Правильно обрабатывать/выдавать заголовки Range/AcceptRange... Google и Wikipedia в помощь...
|
|
#3
|
|||
|
|||
|
удалось нагуглить вот такой код.но в нём есть две строчки которые навероне изза инди10 не работают.
сторчки эти в конце кода, первая: FileStrm := TRangeFileStream(FileName,ARequestInfo.ContentRang eStart, ARequestInfo.ContentRangeEnd); у меня почему-то можно передать только один параметр (FileName) а на остальные два пишет типа не требуются. (Ошибка [Error] Unit1.pas(122): ')' expected but ',' found ) и вторая строчка, AThread.Connection.WriteBuffer(LBuf, LNumRead); в инди10 вместо Athread используется AContext и функции Connection.WriteBuffer нету тут. Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPServer, IdCustomHTTPServer,
IdHTTPServer, StdCtrls,IdContext,math;
type
TForm1 = class(TForm)
IdHTTPServer1: TIdHTTPServer;
Memo1: TMemo;
Edit1: TEdit;
procedure IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
private
{ Private declarations }
public
{ Public declarations }
end;
TRangeFileStream = class(TFileStream)
private
FRangeStart, FRangeEnd: Cardinal;
FRangeEnabled: Boolean;
function GetAbsolutePosition: Longint;
protected
property AbsolutePosition: Longint read GetAbsolutePosition;
public
constructor Create(const AFileName: String; ARangeStart, ARangeEnd:
Cardinal);
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
property RangeStart: Cardinal read FRangeStart;
property RangeEnd: Cardinal read FRangeEnd;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
constructor TRangeFileStream.Create(const AFileName: String; ARangeStart, ARangeEnd: Cardinal);
var
LSize: Longint;
begin
inherited Create(AFileName, fmOpenRead or fmShareDenyWrite);
LSize := Self.Size;
if ARangeStart > LSize then begin
ARangeStart := LSize;
end;
if ARangeEnd > LSize then begin
ARangeEnd := LSize;
end;
FRangeEnabled := (ARangeStart <= ARangeEnd) and (ARangeEnd <> 0);
if FRangeEnabled then begin
FRangeStart := ARangeStart;
FRangeEnd := ARangeEnd;
end;
end;
function TRangeFileStream.GetAbsolutePosition: Longint;
begin
Result := inherited Seek(0, soFromCurrent);
end;
function TRangeFileStream.Read(var Buffer; Count: Longint): Longint;
var
LBytesLeft: Cardinal;
begin
if FRangeEnabled then begin
LBytesLeft := (FRangeEnd+1) - AbsolutePosition;
if Count > LBytesLeft then begin
Count := LBytesLeft;
end;
end;
Result := inherited Read(Buffer, Count);
end;
function TRangeFileStream.Seek(Offset: Longint; Origin: Word): Longint;
var
LPos: Longint;
begin
if FRangeEnabled then begin
Case Origin of
soFromBeginning: Offset := FRangeStart + Offset;
soFromCurrent: Offset := AbsolutePosition + Offset;
soFromEnd: Offset := (FRangeEnd+1) + Offset;
end;
Offset := Max(Offset, FRangeStart);
Offset := Min(Offset, FRangeEnd+1);
Origin := soFromBeginning;
end;
Result := inherited Seek(Offset, Origin);
end;
//============
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
FileStrm: TRangeFileStream;
LSize, LNumRead: Integer;
LBuf: array[0..1023] of Byte;
FileName:string;
begin
//...
FileStrm := TRangeFileStream(FileName,
ARequestInfo.ContentRangeStart, ARequestInfo.ContentRangeEnd);
try
LSize := FileStrm.Size;
AResponseInfo.ContentType :='...'; //
AResponseInfo.ContentLength := LSize;
AResponseInfo.ContentRangeStart := FileStrm.RangeStart;
AResponseInfo.ContentRangeEnd := FileStrm.RangeEnd;
AResponseInfo.WriteHeader;
FileStrm.Position := 0;
while FileStrm.Position < LSize do
begin
LNumRead := FileStrm.Read(LBuf, Sizeof(LBuf));
if (LNumRead > 0) then begin
AThread.Connection.WriteBuffer(LBuf, LNumRead);
end;
end;
finally
FileStrm.Free;
end;
end;
end.
Последний раз редактировалось Snake22, 30.11.2012 в 20:15. |
|
#4
|
||||
|
||||
|
TRangeFileStream.Create
AResponseInfo.ContentStream |
|
#5
|
||||
|
||||
|
Вот тут ещё посмотреть можно: http://www.delphigroups.info/2/3b/184348.html
|
|
#6
|
|||
|
|||
|
Ого,спасибо)
Такс,теперь надо разобраться. по ссылочке в принципе понятно о чём речь ,что в инди9 ошбика была и надо вручную строчку одну добавить в исходники idhttpserver'a, но,у меняж инди10 ,неужели там не исправили это? и главное, что делать с TRangeFileStream.Create AResponseInfo.ContentStream ? |
|
#7
|
||||
|
||||
|
Первое - это решение первой ошибки. У тебя приведение типа
Код:
TRangeFileStream(Object); Код:
TRangeFileStream.Create(param1, param2, etc...); Второе - это поток данных (TStream), используемый для отправки. Гугл в помощь, как говорится. |
|
#8
|
|||
|
|||
|
c первым разобрался,про второе непонятно.
там же,как я понял, циклом,до тех пор пока не дойдем до конца файла,передаём клиенту куски файла Код:
while FileStrm.Position < LSize do begin LNumRead := FileStrm.Read(LBuf, Sizeof(LBuf)); if (LNumRead > 0) then begin AThread.Connection.WriteBuffer(LBuf, LNumRead); end; Код:
AResponseInfo.ContentStream:=TFileStream.Create('FileName',fmShareDenyNone);а если заменить Код:
AThread.Connection.WriteBuffer(LBuf, LNumRead); Код:
AResponseInfo.ContentStream.Write(LBuf, LNumRead); |
|
#9
|
||||
|
||||
|
Не-не, всё проще. TRangeFileStream.Create как раз создаёт поток, который содержит необходимые для передачи данные (только передаваемый кусок). Всё что надо - это присвоить этот поток параметру AResponseInfo.ContentStream, и задать правильные заголовки.
|
|
#10
|
|||
|
|||
|
что то ничего не получается(((
AResponseInfo.ContentStream:=FileStrm выдает ошибку при попытке скачать файл |
|
#11
|
||||
|
||||
|
Дежурный телепат форума в отпуске, так что вынужден спросить - "что за ошибка"?
|
|
#12
|
|||
|
|||
|
ошибку Access violation error
словно AResponseInfo.ContentStream не создан а мы ему пытаемся присвоить |
|
#13
|
||||
|
||||
|
В окне evaluate/modify посмотри, может сам AResponseInfo == nil.
|
|
#14
|
|||
|
|||
|
нет.там есть всякие значения.а вот
AResponseInfo.ContentStream равен nil вот код если что Код:
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var FileStrm: TRangeFileStream; LSize, LNumRead: Integer; LBuf: array[0..1023] of Byte; begin //... FileStrm := TRangeFileStream.Create(Edit1.Text,ARequestInfo.ContentRangeStart, ARequestInfo.ContentRangeEnd); LSize := FileStrm.Size; AResponseInfo.ContentType :='video/x-msvideo avi';// для теста пока взял большой файл, фильмец AResponseInfo.ContentLength := LSize; AResponseInfo.ContentRangeStart := FileStrm.RangeStart; AResponseInfo.ContentRangeEnd := FileStrm.RangeEnd; AResponseInfo.WriteHeader; FileStrm.Position := 0; AResponseInfo.ContentStream:=FileStrm; end; |
|
#15
|
||||
|
||||
|
Мэд, вряд ли, эти параметры не var, должны быть созданы до вызова.
Похоже, что косяк где-то в другом месте. Погуляй по коду трейсом в дебаге (бряк на начало процедуры и F8 до конца), и посмотри, на какой строчке валится AV. |