delphi - 具有恢复支持的 Indy Http Server

标签 delphi tcp c++builder indy httpserver

我已经编写了一个独立的 http 服务器,我想提供支持恢复的文件下载服务。当我使用 IDM 下载文件时,下载是单线程的:

enter image description here

请注意,恢复能力,但是当我暂停并恢复下载时,它会从头开始。

我的 Indy Http 服务器是这样的:

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();
}

如有任何帮助,我们将不胜感激。

最佳答案

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!
}

关于delphi - 具有恢复支持的 Indy Http Server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21494524/

相关文章:

delphi - Delphi 和 Rad Studio 有什么区别?

delphi - 使用Delphi中的十六进制内存值进行常量单

javascript - 无序的 websocket 消息(不要等待丢失数据包的重传)

c - unix中绑定(bind)端口 "Address already in use"TCP套接字编程错误

PHP Mysqli 不关闭 TCP 连接

delphi - 从 ComboBox DrawItem 事件中的 TImageList 复制透明(32 位 alpha)位图

delphi - 从汇编例程访问 Delphi 记录、类等之后的第一个字节

delphi - 如何更改 FM2 中 StringGrid 的字体大小

delphi - Delphi 中的 trie 实现?

c++ - 锁定后我应该解锁 TBitmap Canvas 吗?