Create video streaming server in indy

前端 未结 1 343
忘掉有多难
忘掉有多难 2021-01-23 14:27

I am trying to create video streaming server using Indy Http server. I am using ranged requests to send large files. One chunk of data is 10 Mb long. If video file which request

相关标签:
1条回答
  • 2021-01-23 14:42

    There are several errors in your server code.

    You are not validating that a range is actually being requested, or even respecting an end range if one is present.

    You are setting the AResponseInfo.ContentLength property to the full size of the file, even when you are not sending the full file at one time. That value belongs in the AResponseInfo.ContentRangeInstanceLength property instead when sending a ranged response. You must set ContentLength to the size of the data actually being sent in the response, which in this case is your current range chunk. It is best not to set the ContentLength at all, you can let the server calculate it for you based on the assigned ContentStream.

    You are setting the AResponseInfo.ResponseNo property to 206 unconditionally, even if a range is not requested at all, or if the requested range cannot be satisfied. TIdHTTPRangeStream performs validations in its constructor and sets its ResponseCode property accordingly. That is the value you should be assigning to ResponseNo.

    Try something more like this instead:

    procedure TForm1.External_Get(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    var
      FS: TFileStream;
      Range: TIdEntityRange;
      StartPos, EndPos: Int64;
    begin
      if not FileExists('/home/user/Desktop/large_file.mp4') then
      begin
        AResponseInfo.ResponseNo := 404;
        Exit;
      end;
    
      try
        FS := TFileStream.Create('/home/user/Desktop/large_file.mp4', fmOpenRead or fmShareDenyWrite);
      except
        AResponseInfo.ResponseNo := 500;
        Exit;
      end;
    
      AResponseInfo.ContentType := 'video/mp4';
      AResponseInfo.AcceptRanges := 'bytes';
    
      if ARequestInfo.Ranges.Count = 1 then
      begin
        Range := ARequestInfo.Ranges.Ranges[0];
    
        StartPos := Range.StartPos;
        EndPos := Range.EndPos;
    
        if StartPos >= 0 then
        begin
          // requesting prefix range from BOF
          if EndPos >= 0 then
            EndPos := IndyMin(EndPos, StartPos + (1024*1024*10) - 1)
          else
            EndPos := StartPos + (1024*1024*10) - 1;
        end else
        begin
          // requesting suffix range from EOF
          if EndPos >= 0 then
            EndPos := IndyMin(EndPos, 1024*1024*10)
          else
            EndPos := (1024*1024*10);
        end;
    
        AResponseInfo.ContentStream := TIdHTTPRangeStream.Create(FS, StartPos, EndPos);
        AResponseInfo.ResponseNo := TIdHTTPRangeStream(AResponseInfo.ContentStream).ResponseCode;
    
        if AResponseInfo.ResponseNo = 206 then
        begin
          AResponseInfo.ContentRangeStart := TIdHTTPRangeStream(AResponseInfo.ContentStream).RangeStart;
          AResponseInfo.ContentRangeEnd := TIdHTTPRangeStream(AResponseInfo.ContentStream).RangeEnd;
          AResponseInfo.ContentRangeInstanceLength := FS.Size;
        end;
      end else
      begin
        AResponseInfo.ContentStream := FS;
        AResponseInfo.ResponseNo := 200;
      end;
    end; 
    
    0 讨论(0)
提交回复
热议问题