从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
相关产品推荐
相关产品推荐

