从流加载图像 - 范围检查错误

时间:2014-04-02 02:14:46

标签: delphi delphi-xe5

我试图通过Stream向客户端发送DataSnap服务器的图片,更多的尝试在客户端上打开流我收到错误"范围检查错误" 我得到了这个url的图像,需要通过流或其他方式发送给客户端。

    //SERVER
function TServerMethods1.DownloadImage(xUrlImg : String; out resp : String) : TStream;
var
  HTTP : TIdHttp;
  Stream : TStream;
  Image : TImage;
  stemp : String;
begin
 try
    HTTP := TIdHttp.Create(nil);
    try
      Stream := TMemoryStream.Create;
      try
        HTTP.ReadTimeout := 10000;
        HTTP.ConnectTimeout := 10000;
        HTTP.Get(xUrlImg, Stream);
        Stream.Position := 0;

        Image := TImage.Create(nil);
        Image.BitMap := TBitMap.Create(0, 0);
        Image.BitMap.LoadFromStream(Stream);
        sTEmp := DateTimeToStr(now).Replace('/', '').Replace(':', '') + '.jpg';
        Image.Bitmap.SaveToFile('C:\SISTEMAS\MOBILE\' + stemp);
        //Image.Free;

        Result := TMemoryStream.Create;
        Image.Bitmap.SaveToStream(Result);
        Result.Seek( 0, TSeekOrigin.soBeginning );
        Result.Position := 0;
        Image.Free;
        //Result.CopyFrom(Stream, 0);
        Stream.Free;
      finally
        //img := Stream;
        resp := '';
        //Stream.Free
      end
    finally
      HTTP.Free
    end;
 Except
   ON E: Exception do
     begin
       resp := 'ERRO: ' + E.Message;
     end;
 end;
end;

//客户端

    function TFPrin.SalvaImg(URL, xNomeImg : String) : Boolean;
var
  Stream : TStream;
  Image : TImage;
  pathImage,
  sTemp : String;
begin
 try
  Stream := TMemoryStream.Create;
  Stream := ClientModule1.ServerMethods1Client.DownloadImage(URL, sTemp);
  Stream.Position := 0;
  if Trim(sTemp) <> '' then
     begin
      //Stream.Free;
      ShowMessage('Erro: ' + sTemp);
      Exit;
     end;

  pathImage := GetDirPlat + xNomeImg;
  Image := TImage.Create(nil);
  //Image.BitMap := TBitMap.Create(0, 0);
  Image.BitMap.LoadFromStream(Stream);  **//ERROR - RANGE CHECK ERROR**
  Image.Bitmap.SaveToFile(pathImage);
  Image.Free;
  //Stream.Free

 Except
  On E: Exception do
    begin
       ShowMessage('Erro gerar imagem: ' + e.Message);
    end;
 end;
end;

2 个答案:

答案 0 :(得分:3)

您的代码存在许多缺陷:

  • 一开始是凌乱而充满评论的。仅这一点就让你很难看到发生的事情。
  • 你正在泄露记忆。至少一个内存流,可能更多。如果静态分析无法找到它们,请使用完整的FastMM调试来跟踪并解决这些泄漏。
  • 您错误地使用了TImage。这是一个GUI控件。如果需要使用位图,请直接使用TBitmap
  • 但您不需要使用位图。您要做的就是将文件从一台机器发送到另一台机器。

删除所有TBitmapTImage代码。而是通过将流直接加载并保存到磁盘来在机器之间传输文件。然后使用Indy组件传输流。您需要TFileStream

完成此操作后,您的代码将变得更加简单。如果您仍然有错误,可以在与您真正需要的代码相关的上下文中进行调查。

您的范围检查错误似乎位于您应删除的代码中,该代码适用于位图。这就是为什么我没有直接解决错误的原因。因为无论如何都应删除该代码。

因此,作为示例,对TIdHttp.Get的调用可以这样编写:

var
  FileStream: TFileStream;
....
FileStream := TFileStream.Create(FileName, fmCreate);
try
  HTTP.Get(xUrlImg, FileStream);
finally
  FileStream.Free;
end;

现在你已经保存了文件。将其扩展为传输到内存流结果变量,如下所示:

Result := TMemoryStream.Create;
try
  FileStream := TFileStream.Create(FileName, fmCreate);
  try
    HTTP.Get(xUrlImg, FileStream);
    FileStream.Position := 0;
    Result.CopyFrom(FileStream, FileStream.Size);
  finally
    FileStream.Free;
  end;
except
  Result.Free;
  raise;
end;

或者如果你想读入内存流,然后复制到这样的文件:

Result := TMemoryStream.Create;
try
  HTTP.Get(xUrlImg, Result);
  FileStream := TFileStream.Create(FileName, fmCreate);
  try
    Result.Position := 0;
    FileStream.CopyFrom(Result, Result.Size);
  finally
    FileStream.Free;
  end;
except
  Result.Free;
  raise;
end;

您的客户端代码如下所示:

function TFPrin.SalvaImg(URL, xNomeImg: string): Boolean;
var
  Stream: TStream;
begin
  Stream := ClientModule1.ServerMethods1Client.DownloadImage(URL, sTemp);
  try
    Stream.Position := 0;
    FileStream := TFileStream.Create(GetDirPlat + xNomeImg, fmCreate);
    try
      FileStream.CopyFrom(Stream, Stream.Size);
    finally
      FileStream.Free;
    end;
  finally
    Stream.Free;
  end;
end;

答案 1 :(得分:0)

尝试更像这样的事情:

//Server
function TServerMethods1.DownloadImage(xUrlImg : String; out resp : String) : TStream;
var
  HTTP : TIdHttp;
  Stream : TStream;
  Bmp : TBitmap;
  Fmt: TFormatSettings;
begin
  Result := nil;
  try
    Stream := TMemoryStream.Create;
    try
      HTTP := TIdHttp.Create(nil);
      try
        HTTP.ReadTimeout := 10000;
        HTTP.ConnectTimeout := 10000;
        HTTP.Get(xUrlImg, Stream);
      finally
        HTTP.Free;
      end;

      Bmp := TBitmap.Create(0, 0);
      try
        Stream.Position := 0;
        Bmp.LoadFromStream(Stream);

        Fmt := TFormatSettings.Create;
        Fmt.DateSeparator := #0;
        Fmt.TimeSeparator := #0;
        Bmp.SaveToFile('C:\SISTEMAS\MOBILE\' + DateTimeToStr(Now, Fmt) + '.jpg');

        Stream.Clear;
        Bmp.SaveToStream(Stream);
        Stream.Position := 0;
      finally
        Bmp.Free;
      end
    except
      Stream.Free;
      raise;
    end;
    Result := Stream;
  except
    on E: Exception do
    begin
      resp := 'ERRO: ' + E.Message;
    end;
  end;
end;

//client
function TFPrin.SalvaImg(URL, xNomeImg : String) : Boolean;
var
  Stream : TStream;
  Bmp : TBitmap;
  sTemp : String;
begin
  try
    Stream := ClientModule1.ServerMethods1Client.DownloadImage(URL, sTemp);
    if Stream = nil then
    begin
      ShowMessage('Erro: ' + sTemp);
      Exit;
    end;
    try
      Bmp := TBitmap.Create(0, 0);
      try
        Bmp.LoadFromStream(Stream);
        Bmp.SaveToFile(GetDirPlat + xNomeImg);
      finally
        Bmp.Free;
      end;
    finally
      Stream.Free;
    end;
  except
    on E: Exception do
    begin
      ShowMessage('Erro gerar imagem: ' + e.Message);
    end;
  end;
end;