|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
докачка в idhttpserver
Помогите сделать докачку при скачивании с idhttpserver.
у меня программа-сервак (idhttpserver) раздаёт файлы, и в случае обрыва скачивание начинается сначала. сервер версии инди10 Последний раз редактировалось Snake22, 30.11.2012 в 18:53. |
#2
|
||||
|
||||
Правильно обрабатывать/выдавать заголовки Range/AcceptRange... Google и Wikipedia в помощь...
Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |
#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 Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |
#5
|
||||
|
||||
Вот тут ещё посмотреть можно: http://www.delphigroups.info/2/3b/184348.html
Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |
#6
|
|||
|
|||
Ого,спасибо)
Такс,теперь надо разобраться. по ссылочке в принципе понятно о чём речь ,что в инди9 ошбика была и надо вручную строчку одну добавить в исходники idhttpserver'a, но,у меняж инди10 ,неужели там не исправили это? и главное, что делать с TRangeFileStream.Create AResponseInfo.ContentStream ? |
#7
|
||||
|
||||
Первое - это решение первой ошибки. У тебя приведение типа
Код:
TRangeFileStream(Object); Код:
TRangeFileStream.Create(param1, param2, etc...); Второе - это поток данных (TStream), используемый для отправки. Гугл в помощь, как говорится. Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |
#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, и задать правильные заголовки.
Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |
#10
|
|||
|
|||
что то ничего не получается(((
AResponseInfo.ContentStream:=FileStrm выдает ошибку при попытке скачать файл |
#11
|
||||
|
||||
Дежурный телепат форума в отпуске, так что вынужден спросить - "что за ошибка"?
Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |
#12
|
|||
|
|||
ошибку Access violation error
словно AResponseInfo.ContentStream не создан а мы ему пытаемся присвоить |
#13
|
||||
|
||||
В окне evaluate/modify посмотри, может сам AResponseInfo == nil.
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#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. Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj |