2014-02-01 3 views
3

Я написал indy http-сервер, я хочу загрузить файл с поддержкой резюме. Когда я использую IDM, чтобы загрузить файл, загрузка однопоточен:Indy Http Server с поддержкой резюме

enter image description here

Обратите внимание, что способность Резюме является Да, но когда я делаю паузу и возобновить загрузку, он начинает форму начала.

Мой Indy HTTP Server как:

void __fastcall TfrmMain::httpServerCommandGet(TIdContext *AContext, 
    TIdHTTPRequestInfo *ARequestInfo, TIdHTTPResponseInfo *AResponseInfo) 
{ 
    Beep(1000, 100); 
    string fileName = ExtractFileDir(Application->ExeName) + ARequestInfo->Document; 
    fileName = fileName.replace("/", "\\"); 

    TFileStream *stream = new TFileStream(fileName, fmOpenRead | fmShareDenyNone); 

    int start = 0, end = 0; 
    string range = ARequestInfo->Range; 
    if(!range.empty()) 
    { 
     int dash_pos = range.find("-"); 
     start = range.substr(0, dash_pos).intValue(); 
     end = range.substr(dash_pos + 1).intValue(); 
     if(end == 0) // Endless Range: start- 
      end = stream->Size; 
    } 
    else 
    { 
     start = 0; 
     end = stream->Size; 
    } 
    OutputDebugStringW(string("ctx=[] start=[] end=[]") << 
     IntToHex((int)AContext, 8) << start << end); 

    stream->Seek((__int64)start, soBeginning); 
    AResponseInfo->ContentStream = stream; 
    AResponseInfo->FreeContentStream = true; 
    AResponseInfo->ContentLength = stream->Size; 
    if(!range.empty()) 
    { 
     AResponseInfo->ContentRangeStart = start; 
     AResponseInfo->ContentRangeEnd = end; 
     AResponseInfo->ResponseNo = 206; 
     AResponseInfo->ContentRangeInstanceLength = end + 1; 
     AResponseInfo->ContentLength = end - start + 1; 
     AResponseInfo->AcceptRanges = "bytes"; 
    } 
    AResponseInfo->WriteHeader(); 
    AResponseInfo->WriteContent(); 
} 

любая помощь будет оценена.

ответ

5

Узел IdCustomHTTPServer имеет вспомогательный класс TIdHTTPRangeStream для этой самой цели.

Если клиент запрашивает дистанционную загрузку, создать экземпляр TIdHTTPRangeStream и передать его от предполагаемого TStream и требуемый диапазон клиента, а затем назначить его в качестве ContentStream для отправки. TIdHTTPRangeStream также имеет свойство ResponseCode, которое необходимо присвоить объекту ResponseNo ответа.

Например:

void __fastcall TfrmMain::httpServerCommandGet(TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo, TIdHTTPResponseInfo *AResponseInfo) 
{ 
    // create file stream ... 

    // THTTPServer parses the ranges for you 
    if (ARequestInfo->Ranges->Count > 0) 
    { 
     if (ARequestInfo->Ranges->Count > 1) 
     { 
      AResponseInfo->ResponseNo = 416; 
      return; 
     } 

     TIdEntityRange *range = ARequestInfo->Ranges->Range[0]; 

     TIdHTTPRangeStream *rstream = new TIdHTTPRangeStream(stream, range->StartPos, range->EndPos, true); 

     AResponseInfo->ResponseNo = rstream->ResponseCode; 
     AResponseInfo->ContentRangeStart = rstream->RangeStart; 
     AResponseInfo->ContentRangeEnd = rstream->RangeEnd; 
     AResponseInfo->ContentStream = rstream; 
     AResponseInfo->AcceptRanges = "bytes"; 
    } 
    else 
    { 
     AResponseInfo->ContentStream = stream; 
    } 

    // no need to seek the target stream manually 
    // no need to set the ContentLength manually 
    // no need to call WriteHeader() and WriteContent() manually 
    // 
    // TIdHTTPServer handles all that for you internally! 
} 
+0

Великий ответ, он работал, большое спасибо. –

Смежные вопросы