You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从PostgreSQL读取图片到TImage组件时触发EEncodingError错误求助

问题:PostgreSQL读取图片到TImage时触发EEncodingError错误

我使用PgDac库操作PostgreSQL数据库,将TImage组件中的图片存入user_profile_pic字节数组列,读取后在另一TImage组件展示。大部分图片可正常读写,但读取某张David Bowie的图片时触发错误:

Project MyProject.exe raised exception class EEncodingError with message 'No mapping for the Unicode character exists in the target multi-byte code page'

错误发生在imgGetImgFromDB.Picture.LoadFromStream(stream)语句处,其他图片(如Delphi Logo图片)可正常读取。

上传图片代码

procedure TfrmMyForm.btnUploadImageClick(Sender: TObject);
var
  AStream: TMemoryStream;
begin
  //fileExtension gets used while uploading the image to a TImage.
  pgqUploadProfilePicture.SQL.Text := 'INSERT INTO users_tbl (user_profile_extension, user_profile_pic)';
  pgqUploadProfilePicture.SQL.Add('VALUES (:ProfilePictureExtension, :ProfilePicture)');
  pgqUploadProfilePicture.ParamByName('ProfilePictureExtension').AsString := fileExtension; 
  //saves the image to a format that is used by the database
  AStream := TMemoryStream.Create;
  try
    imgProfilePicture.Picture.SaveToStream(AStream);
    pgqUploadProfilePicture.ParamByName('ProfilePicture').LoadFromStream(AStream, ftBlob);
    pgqUploadProfilePicture.Execute;    

  finally
    AStream.Free;
  end;
end;

读取图片代码

//user gets retrieved in another method
procedure TfrmGetImage.btnGetImageFromDB(Sender: TObject);
var
  stream: TStream;
begin
  //get image from retrieved user
  stream := pgqCheckExistingUser.CreateBlobStream(pgqCheckExistingUser.FieldByName('user_profile_pic'), bmRead);
  stream.Position := 0;
  imgGetImgFromDB.Picture.LoadFromStream(stream);
end;

解决方法

1. 直接保存图片原始字节流

当前上传逻辑用TImage.Picture.SaveToStream保存的是Delphi内部封装的图片格式(可能携带Unicode元数据),换成直接读取图片文件的原始字节流存入数据库,避免编码干扰:

procedure TfrmMyForm.btnUploadImageClick(Sender: TObject);
var
  AStream: TFileStream;
begin
  pgqUploadProfilePicture.SQL.Text := 'INSERT INTO users_tbl (user_profile_extension, user_profile_pic)';
  pgqUploadProfilePicture.SQL.Add('VALUES (:ProfilePictureExtension, :ProfilePicture)');
  pgqUploadProfilePicture.ParamByName('ProfilePictureExtension').AsString := fileExtension; 
  // 直接读取图片文件的原始字节流
  AStream := TFileStream.Create(OpenPictureDialog.FileName, fmOpenRead or fmShareDenyWrite);
  try
    pgqUploadProfilePicture.ParamByName('ProfilePicture').LoadFromStream(AStream, ftBlob);
    pgqUploadProfilePicture.Execute;    
  finally
    AStream.Free;
  end;
end;

2. 读取时指定图片格式加载

若无法修改上传逻辑,读取时根据存储的扩展名显式指定图形类,避免自动识别时触发编码错误:

procedure TfrmGetImage.btnGetImageFromDB(Sender: TObject);
var
  stream: TStream;
  Ext: string;
  GraphicClass: TGraphicClass;
begin
  // 获取图片扩展名
  Ext := pgqCheckExistingUser.FieldByName('user_profile_extension').AsString;
  // 根据扩展名匹配对应图形类
  if SameText(Ext, 'png') then
    GraphicClass := TPngImage
  else if SameText(Ext, 'jpg') or SameText(Ext, 'jpeg') then
    GraphicClass := TJPEGImage
  else if SameText(Ext, 'bmp') then
    GraphicClass := TBitmap
  else
    raise Exception.Create('不支持的图片格式');

  stream := pgqCheckExistingUser.CreateBlobStream(pgqCheckExistingUser.FieldByName('user_profile_pic'), bmRead);
  try
    stream.Position := 0;
    imgGetImgFromDB.Picture.Graphic := GraphicClass.Create;
    try
      imgGetImgFromDB.Picture.Graphic.LoadFromStream(stream);
    finally
      imgGetImgFromDB.Picture.Graphic.Free;
    end;
  finally
    stream.Free;
  end;
end;

3. 确认PgDac的Blob参数类型

上传时显式指定参数类型为ftBlob,避免自动推断导致的编码转换:
在LoadFromStream前添加:

pgqUploadProfilePicture.ParamByName('ProfilePicture').DataType := ftBlob;

内容的提问来源于stack exchange,提问作者PlastikLight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 22:31:21